added compatabily network interface android 11

This commit is contained in:
2022-08-08 15:39:29 +01:00
parent 39d456b73d
commit a627828ea5
9 changed files with 727 additions and 63 deletions

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_XL_API_28.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-12-25T13:07:42.839537Z" />
</component>
</project>

1
.idea/gradle.xml generated
View File

@@ -13,7 +13,6 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>

View File

@@ -9,9 +9,9 @@ android {
defaultConfig {
applicationId "com.peernet.mobile"
minSdk 24
targetSdk 31
versionCode 1
versionName "1.0"
targetSdk 32
versionCode 2
versionName "2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -36,18 +36,18 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.android.volley:volley:1.2.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.2'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation (name:'mobile', ext:'aar')
implementation 'com.vmadalin:easypermissions-ktx:1.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.8.1'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
//compile 'io.github.rybalkinsd:kohttp:0.10.0'
}

Binary file not shown.

Binary file not shown.

View File

@@ -11,6 +11,8 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- CHANGE_WIFI_MULTICAST_STATE is required for local discovery to work on Android 11 "R" -->
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<application
android:allowBackup="true"

View File

@@ -0,0 +1,61 @@
package com.peernet.test;
import android.annotation.SuppressLint;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.List;
public class GetInterfacesGo {
// Returns details of the interfaces in the system, encoded as a single string for ease
// of JNI transfer over to the Go environment.
//
// Example:
// rmnet_data0 10 2000 true false false false false | fe80::4059:dc16:7ed3:9c6e%rmnet_data0/64
// dummy0 3 1500 true false false false false | fe80::1450:5cff:fe13:f891%dummy0/64
// wlan0 30 1500 true true false false true | fe80::2f60:2c82:4163:8389%wlan0/64 10.1.10.131/24
// r_rmnet_data0 21 1500 true false false false false | fe80::9318:6093:d1ad:ba7f%r_rmnet_data0/64
// rmnet_data2 12 1500 true false false false false | fe80::3c8c:44dc:46a9:9907%rmnet_data2/64
// r_rmnet_data1 22 1500 true false false false false | fe80::b6cd:5cb0:8ae6:fe92%r_rmnet_data1/64
// rmnet_data1 11 1500 true false false false false | fe80::51f2:ee00:edce:d68b%rmnet_data1/64
// lo 1 65536 true false true false false | ::1/128 127.0.0.1/8
// v4-rmnet_data2 68 1472 true true false true true | 192.0.0.4/32
//
// Where the fields are:
// name ifindex mtu isUp hasBroadcast isLoopback isPointToPoint hasMulticast | ip1/N ip2/N ip3/N;
@SuppressLint("DefaultLocale")
public static String GetInterfacesAsString() {
List<NetworkInterface> interfaces;
try {
interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
} catch (Exception e) {
return "";
}
StringBuilder sb = new StringBuilder("");
for (NetworkInterface nif : interfaces) {
try {
// Android doesn't have a supportsBroadcast() but the Go net.Interface wants
// one, so we say the interface has broadcast if it has multicast.
sb.append(String.format("%s %d %d %b %b %b %b %b |", nif.getName(),
nif.getIndex(), nif.getMTU(), nif.isUp(), nif.supportsMulticast(),
nif.isLoopback(), nif.isPointToPoint(), nif.supportsMulticast()));
for (InterfaceAddress ia : nif.getInterfaceAddresses()) {
// InterfaceAddress == hostname + "/" + IP
String[] parts = ia.toString().split("/", 0);
if (parts.length > 1) {
sb.append(String.format("%s/%d ", parts[1], ia.getNetworkPrefixLength()));
}
}
} catch (Exception e) {
// TODO(dgentry) should log the exception not silently suppress it.
continue;
}
sb.append("\n");
}
return sb.toString();
}
}

View File

@@ -1,67 +1,70 @@
package com.peernet.test
import android.Manifest
import android.content.ContentValues.TAG
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.vmadalin.easypermissions.EasyPermissions
import com.vmadalin.easypermissions.annotations.AfterPermissionGranted
import mobile.Mobile
import androidx.core.app.ActivityCompat.requestPermissions
import android.net.wifi.WifiManager
import android.os.Build
import android.provider.Settings
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat.requestPermissions
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import com.android.volley.Request
import com.android.volley.Request.Method.GET
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.util.*
import kotlin.concurrent.schedule
import android.provider.MediaStore
import java.io.File
import android.os.Environment
import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.JsonRequest
import mobile.Mobile
import org.json.JSONArray
import org.json.JSONObject
import org.json.JSONTokener
import android.net.NetworkInfo
import android.net.ConnectivityManager
import android.os.Handler
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.net.toFile
import androidx.core.net.toUri
import java.nio.file.Files
import java.nio.file.Paths
import android.net.wifi.WifiManager.MulticastLock;
import java.util.*
import kotlin.concurrent.schedule
class MainActivity : AppCompatActivity() {
private val wifiManager: WifiManager get() = this.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Mobile.mobileMain(this.filesDir.absolutePath)
val Interface = GetInterfacesGo.GetInterfacesAsString()
Log.d("Interface", Interface);
// See issue #735: Android 11 blocks local discovery if we did not acquire MulticastLock.
// See issue #735: Android 11 blocks local discovery if we did not acquire MulticastLock.
var multicastLock =
wifiManager.createMulticastLock("multicastLock")
multicastLock.setReferenceCounted(true)
multicastLock.acquire()
// Start Web Server from the Android side to broadcast
// the information of the network interface
// TinyWebServer.startServer("localhost",9000, "/web/public_html");
Mobile.mobileMain(this.filesDir.absolutePath,Interface)
if (isNetwork(this)){
@@ -124,7 +127,7 @@ class MainActivity : AppCompatActivity() {
numPeers.text = ResponseObject.get("countpeerlist").toString()
// connectionLabel.text = response.toString()
// Log.d("myTag", "Response is: ${response.substring(0, 500)}");
Log.d("myTag", "Response is: ${response}");
},
Response.ErrorListener { errorresponse ->
//val connectionLabel = findViewById<View>(R.id.PeernetInfo) as TextView
@@ -214,6 +217,11 @@ class MainActivity : AppCompatActivity() {
// connectionLabel.text = Mobilecore.mobileCoreStart().toString()
// }
if (multicastLock != null) {
multicastLock.release();
multicastLock = null;
}
}
// fun run(url: String) {
@@ -244,7 +252,7 @@ class MainActivity : AppCompatActivity() {
val path = FileUtils.getPath(this, data?.data)
Log.d("path",path.substring(0, path.lastIndexOf('/')))
//Log.d("path",path.substring(0, path.lastIndexOf('/')))
// convert Path string to URI
val pathUri = path.toUri()

View File

@@ -0,0 +1,611 @@
package com.peernet.test;
/*
* The MIT License
*
* Copyright 2018 Sonu Auti http://sonuauti.com twitter @SonuAuti
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Pattern;
/**
*
* @author Sonu Auti @cis
*/
public class TinyWebServer extends Thread {
/**
* @param args the command line arguments
*/
private static ServerSocket serverSocket;
private final Map<String, String> lowerCaseHeader = new HashMap<>();
public static String CONTENT_TYPE = "text/html";
private String CONTENT_DATE = "";
private String CONN_TYPE = "";
private String Content_Encoding = "";
private String content_length = "";
private String STATUS = "200";
private boolean keepAlive = true;
private String SERVER_NAME = "Firefly http server v0.1";
private static final String MULTIPART_FORM_DATA_HEADER = "multipart/form-data";
private static final String ASCII_ENCODING = "US-ASCII";
private String REQUEST_TYPE = "GET";
private String HTTP_VER = "HTTP/1.1";
//all status
public static String PAGE_NOT_FOUND = "404";
public static String OKAY = "200";
public static String CREATED = "201";
public static String ACCEPTED = "202";
public static String NO_CONTENT = "204";
public static String PARTIAL_NO_CONTENT = "206";
public static String MULTI_STATUS = "207";
public static String MOVED_PERMANENTLY = "301";
public static String SEE_OTHER = "303";
public static String NOT_MODIFIED = "304";
public static String TEMP_REDIRECT = "307";
public static String BAD_REQUEST = "400";
public static String UNAUTHORIZED_REQUEST = "401";
public static String FORBIDDEN = "403";
public static String NOT_FOUND = "404";
public static String METHOD_NOT_ALLOWED = "405";
public static String NOT_ACCEPTABLE = "406";
public static String REQUEST_TIMEOUT = "408";
public static String CONFLICT = "409";
public static String GONE = "410";
public static String LENGTH_REQUIRED = "411";
public static String PRECONDITION_FAILED = "412";
public static String PAYLOAD_TOO_LARGE = "413";
public static String UNSUPPORTED_MEDIA_TYPE = "415";
public static String RANGE_NOT_SATISFIABLE = "416";
public static String EXPECTATION_FAILED = "417";
public static String TOO_MANY_REQUESTS = "429";
public static String INTERNAL_ERROR = "500";
public static String NOT_IMPLEMENTED = "501";
public static String SERVICE_UNAVAILABLE = "503";
public static String UNSUPPORTED_HTTP_VERSION = "505";
public static final String CONTENT_DISPOSITION_REGEX = "([ |\t]*Content-Disposition[ |\t]*:)(.*)";
public static final Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile(CONTENT_DISPOSITION_REGEX, Pattern.CASE_INSENSITIVE);
public static final String CONTENT_TYPE_REGEX = "([ |\t]*content-type[ |\t]*:)(.*)";
public static final Pattern CONTENT_TYPE_PATTERN = Pattern.compile(CONTENT_TYPE_REGEX, Pattern.CASE_INSENSITIVE);
public static final String CONTENT_DISPOSITION_ATTRIBUTE_REGEX = "[ |\t]*([a-zA-Z]*)[ |\t]*=[ |\t]*['|\"]([^\"^']*)['|\"]";
public static final Pattern CONTENT_DISPOSITION_ATTRIBUTE_PATTERN = Pattern.compile(CONTENT_DISPOSITION_ATTRIBUTE_REGEX);
public static final String CONTENT_LENGTH_REGEX = "Content-Length:";
public static final Pattern CONTENT_LENGTH_PATTERN = Pattern.compile(CONTENT_LENGTH_REGEX, Pattern.CASE_INSENSITIVE);
public static final String USER_AGENT = "User-Agent:";
public static final Pattern USER_AGENT_PATTERN = Pattern.compile(USER_AGENT, Pattern.CASE_INSENSITIVE);
public static final String HOST_REGEX = "Host:";
public static final Pattern CLIENT_HOST_PATTERN = Pattern.compile(HOST_REGEX, Pattern.CASE_INSENSITIVE);
public static final String CONNECTION_TYPE_REGEX = "Connection:";
public static final Pattern CONNECTION_TYPE_PATTERN = Pattern.compile(CONNECTION_TYPE_REGEX, Pattern.CASE_INSENSITIVE);
public static final String ACCEPT_ENCODING_REGEX = "Accept-Encoding:";
public static final Pattern ACCEPT_ENCODING_PATTERN = Pattern.compile(ACCEPT_ENCODING_REGEX, Pattern.CASE_INSENSITIVE);
private static final String CONTENT_REGEX = "[ |\t]*([^/^ ^;^,]+/[^ ^;^,]+)";
private static final Pattern MIME_PATTERN = Pattern.compile(CONTENT_REGEX, Pattern.CASE_INSENSITIVE);
private static final String CHARSET_REGEX = "[ |\t]*(charset)[ |\t]*=[ |\t]*['|\"]?([^\"^'^;^,]*)['|\"]?";
private static final Pattern CHARSET_PATTERN = Pattern.compile(CHARSET_REGEX, Pattern.CASE_INSENSITIVE);
private static final String BOUNDARY_REGEX = "[ |\t]*(boundary)[ |\t]*=[ |\t]*['|\"]?([^\"^'^;^,]*)['|\"]?";
private static final Pattern BOUNDARY_PATTERN = Pattern.compile(BOUNDARY_REGEX, Pattern.CASE_INSENSITIVE);
public static String WEB_DIR_PATH="/";
public static String SERVER_IP="localhost";
public static int SERVER_PORT=9000;
public static boolean isStart=true;
public static String INDEX_FILE_NAME="index.html";
public TinyWebServer(final String ip, final int port) throws IOException {
InetAddress addr = InetAddress.getByName(ip); ////"172.31.0.186");
serverSocket = new ServerSocket(port, 100, addr);
serverSocket.setSoTimeout(5000); //set timeout for listner
}
@Override
public void run() {
while (isStart) {
try {
//wait for new connection on port 5000
Socket newSocket = serverSocket.accept();
Thread newClient = new EchoThread(newSocket);
newClient.start();
} catch (SocketTimeoutException s) {
} catch (IOException e) {
}
}//endof Never Ending while loop
}
public class EchoThread extends Thread {
protected Socket socket;
protected boolean nb_open;
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
this.nb_open = true;
}
@Override
public void run() {
try {
DataInputStream in = null;
DataOutputStream out = null;
if (socket.isConnected()) {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
}
byte[] data = new byte[1500];
//socket.setSoTimeout(60 * 1000 * 5);
while (in.read(data) != -1) {
String recData = new String(data).trim();
//System.out.println("received data: \n" + recData);
//System.out.println("------------------------------");
String[] header = recData.split("\\r?\\n");
String contentLen = "0";
String contentType = "text/html";
String connectionType = "keep-alive";
String hostname = "";
String userAgent = "";
String encoding = "";
String[] h1 = header[0].split(" ");
if (h1.length == 3) {
setRequestType(h1[0]);
setHttpVer(h1[2]);
}
for (int h = 0; h < header.length; h++) {
String value = header[h].trim();
//System.out.println(header[h]+" -> "+CONTENT_LENGTH_PATTERN.matcher(header[h]).find());
if (CONTENT_LENGTH_PATTERN.matcher(value).find()) {
contentLen = value.split(":")[1].trim();
} else if (CONTENT_TYPE_PATTERN.matcher(value).find()) {
contentType = value.split(":")[1].trim();
} else if (CONNECTION_TYPE_PATTERN.matcher(value).find()) {
connectionType = value.split(":")[1].trim();
} else if (CLIENT_HOST_PATTERN.matcher(value).find()) {
hostname = value.split(":")[1].trim();
} else if (USER_AGENT_PATTERN.matcher(value).find()) {
for (String ua : value.split(":")) {
if (!ua.equalsIgnoreCase("User-Agent:")) {
userAgent += ua.trim();
}
}
} else if (ACCEPT_ENCODING_PATTERN.matcher(value).find()) {
encoding = value.split(":")[1].trim();
}
}
if (!REQUEST_TYPE.equals("")) {
String postData = "";
if (REQUEST_TYPE.equalsIgnoreCase("POST") && !contentLen.equals("0")) {
postData = header[header.length - 1];
if (postData.length() > 0 && contentLen.length() > 0) {
int len = Integer.valueOf(contentLen);
postData = postData.substring(0, len);
// System.out.println("Post data -> " + contentLen + " ->" + postData);
}
}
// System.out.println("contentLen ->" + contentLen + "\ncontentType ->" + contentType + "\nhostname ->" + hostname + "\nconnectionType-> " + connectionType + "\nhostname ->" + hostname + "\nuserAgent -> " + userAgent);
final String requestLocation = h1[1];
if (requestLocation != null) {
processLocation(out, requestLocation, postData);
}
//System.out.println("requestLocation "+requestLocation);
}
}
} catch (Exception er) {
er.printStackTrace();
}
}
}
public void processLocation(DataOutputStream out, String location, String postData) {
String data = "";
switch (location) {
case "/":
//root location, server index file
CONTENT_TYPE = "text/html";
data=readFile(WEB_DIR_PATH+"/"+INDEX_FILE_NAME);
constructHeader(out, data.length() + "", data);
break;
default:
System.out.println("url location -> " + location);
URL geturl = getDecodedUrl("http://localhost" + location);
String[] dirPath = geturl.getPath().split("/");
String fullFilePath=geturl.getPath();
if (dirPath.length > 1) {
String fileName = dirPath[dirPath.length - 1];
HashMap qparms = (HashMap) splitQuery(geturl.getQuery());
if(REQUEST_TYPE.equals("POST")){
if (qparms==null){ qparms=new HashMap<String,String>();}
qparms.put("_POST", postData);
}
//System.out.println("File name " + fileName);
//System.out.println("url parms " + qparms);
CONTENT_TYPE = getContentType(fileName);
if(!CONTENT_TYPE.equals("text/plain")){
// System.out.println("Full file path - >"+fullFilePath +" "+CONTENT_TYPE);
if(CONTENT_TYPE.equals("image/jpeg") || CONTENT_TYPE.equals("image/png") || CONTENT_TYPE.equals("video/mp4")){
byte[] bytdata=readImageFiles(WEB_DIR_PATH+fullFilePath,CONTENT_TYPE);
//System.out.println(bytdata.length);
if(bytdata!=null){
constructHeaderImage(out, bytdata.length+"", bytdata);
}else{
pageNotFound();
}
}else{
data=readFile(WEB_DIR_PATH+fullFilePath);
if(!data.equals("")){
constructHeader(out, data.length() + "", data);
}else{
pageNotFound();
}
}
}else{
data = getResultByName(fileName, qparms);
constructHeader(out, data.length() + "", data);
}
}
}
}
public URL getDecodedUrl(String parms) {
try {
//String decodedurl =URLDecoder.decode(parms,"UTF-8");
URL aURL = new URL(parms);
return aURL;
} catch (Exception er) {
}
return null;
}
public static HashMap<String, String> splitQuery(String parms) {
try {
final HashMap<String, String> query_pairs = new HashMap<>();
final String[] pairs = parms.split("&");
for (String pair : pairs) {
final int idx = pair.indexOf("=");
final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
if (!query_pairs.containsKey(key)) {
query_pairs.put(key, "");
}
final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
query_pairs.put(key, value);
}
return query_pairs;
} catch (Exception er) {
}
return null;
}
public String getResultByName(String name, HashMap qparms) {
try {
String ClassName = "appapis.queryfiles.AppApis";
Class<?> rClass = Class.forName(ClassName); // convert string classname to class
Object obj = rClass.newInstance(); // invoke empty constructor
Method getNameMethod = obj.getClass().getMethod(name, HashMap.class);
STATUS = TinyWebServer.OKAY;
return getNameMethod.invoke(obj, qparms).toString();
} catch (Exception er) {
// er.printStackTrace();
return pageNotFound();
}
}
public void setRequestType(String type) {
// System.out.println("REQUEST TYPE " + type);
this.REQUEST_TYPE = type;
}
public void setHttpVer(String httpver) {
// System.out.println("REQUEST ver " + httpver);
this.HTTP_VER = httpver;
}
public String getRequestType() {
return this.REQUEST_TYPE;
}
public String getHttpVer() {
return this.HTTP_VER;
}
public String pageNotFound() {
STATUS = NOT_FOUND;
CONTENT_TYPE = "text/html";
//customize your page here
return "<!DOCTYPE html>"
+ "<html><head><title>Page not found | Firefly web server</title>"
+ "</head><body><h3>Requested page not found</h3></body></html>";
}
//hashtable initilization for content types
static Hashtable<String, String> mContentTypes = new Hashtable();
{
mContentTypes.put("js", "application/javascript");
mContentTypes.put("php", "text/html");
mContentTypes.put("java", "text/html");
mContentTypes.put("json", "application/json");
mContentTypes.put("png", "image/png");
mContentTypes.put("jpg", "image/jpeg");
mContentTypes.put("html", "text/html");
mContentTypes.put("css", "text/css");
mContentTypes.put("mp4", "video/mp4");
mContentTypes.put("mov", "video/quicktime");
mContentTypes.put("wmv", "video/x-ms-wmv");
}
//get request content type
public static String getContentType(String path) {
String type = tryGetContentType(path);
if (type != null) {
return type;
}
return "text/plain";
}
//get request content type from path
public static String tryGetContentType(String path) {
int index = path.lastIndexOf(".");
if (index != -1) {
String e = path.substring(index + 1);
String ct = mContentTypes.get(e);
// System.out.println("content type: " + ct);
if (ct != null) {
return ct;
}
}
return null;
}
private void constructHeader(DataOutputStream output, String size, String data) {
SimpleDateFormat gmtFrmt = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output)), false);
pw.append("HTTP/1.1 ").append(STATUS).append(" \r\n");
if (this.CONTENT_TYPE != null) {
printHeader(pw, "Content-Type", this.CONTENT_TYPE);
}
printHeader(pw, "Date", gmtFrmt.format(new Date()));
printHeader(pw, "Connection", (this.keepAlive ? "keep-alive" : "close"));
printHeader(pw, "Content-Length", size);
printHeader(pw, "Server", SERVER_NAME);
pw.append("\r\n");
pw.append(data);
pw.flush();
//pw.close();
}
private void constructHeaderImage(DataOutputStream output, String size, byte[] data) {
try{
SimpleDateFormat gmtFrmt = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output)), false);
pw.append("HTTP/1.1 ").append(STATUS).append(" \r\n");
if (this.CONTENT_TYPE != null) {
printHeader(pw, "Content-Type", this.CONTENT_TYPE);
}
printHeader(pw, "Date", gmtFrmt.format(new Date()));
printHeader(pw, "Connection", (this.keepAlive ? "keep-alive" : "close"));
printHeader(pw, "Content-Length", size);
printHeader(pw, "Server", SERVER_NAME);
pw.append("\r\n");
pw.flush();
output.write(data);
output.flush();
//System.out.println("data sent success");
//pw.close();
}catch(Exception er){er.printStackTrace();}
}
@SuppressWarnings("static-method")
protected void printHeader(PrintWriter pw, String key, String value) {
pw.append(key).append(": ").append(value).append("\r\n");
}
public byte[] readImageFiles(String fileName,String filetype){
try{
File ifile=new File(fileName);
if(ifile.exists()){
if(filetype.equalsIgnoreCase("image/png") || filetype.equalsIgnoreCase("image/jpeg") || filetype.equalsIgnoreCase("image/gif") || filetype.equalsIgnoreCase("image/jpg")){
FileInputStream fis = new FileInputStream(fileName);
byte[] buffer = new byte[fis.available()];
while (fis.read(buffer) != -1) {}
fis.close();
return buffer;
}
}else{
}
}catch(Exception er){}
return null;
}
public String readFile(String fileName){
String content="";
try{
File ifile=new File(fileName);
if(ifile.exists()){
FileInputStream fis = new FileInputStream(fileName);
byte[] buffer = new byte[10];
StringBuilder sb = new StringBuilder();
while (fis.read(buffer) != -1) {
sb.append(new String(buffer));
buffer = new byte[10];
}
fis.close();
content = sb.toString();
}else{
pageNotFound();
return content;
}
}catch(Exception er){
pageNotFound();
return "";
}
return content;
}
public static void init(String ip,int port,String public_dir){
SERVER_IP=ip;
SERVER_PORT=port;
WEB_DIR_PATH=public_dir;
scanFileDirectory();
}
public static void startServer(String ip,int port,String public_dir){
try {
isStart=true;
init(ip,port,public_dir);
Thread t = new TinyWebServer(SERVER_IP, SERVER_PORT);
t.start();
System.out.println("Server Started !");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
}
}
public static void stopServer(){
if(isStart){
try{
isStart=false;
serverSocket.close();
System.out.println("Server stopped running !");
}catch(IOException er){
er.printStackTrace();
}
}
}
//scan for index file
public static void scanFileDirectory(){
boolean isIndexFound=false;
try{
File file=new File(WEB_DIR_PATH);
if(file.isDirectory()){
File[] allFiles=file.listFiles();
for (File allFile : allFiles) {
//System.out.println(allFile.getName().split("\\.")[0]);
if(allFile.getName().split("\\.")[0].equalsIgnoreCase("index")){
TinyWebServer.INDEX_FILE_NAME=allFile.getName();
isIndexFound=true;
}
}
}
}catch(Exception er){}
if(!isIndexFound){
System.out.println("Index file not found !");
}
}
/* //use for testing
public static void main(String[] args) {
try {
Thread t = new TinyWebServer(SERVER_IP, SERVER_PORT);
t.start();
System.out.println("Server Started !");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
}
}*/
}