added compatabily network interface android 11
This commit is contained in:
17
.idea/deploymentTargetDropDown.xml
generated
17
.idea/deploymentTargetDropDown.xml
generated
@@ -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
1
.idea/gradle.xml
generated
@@ -13,7 +13,6 @@
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
@@ -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.
@@ -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"
|
||||
|
||||
61
app/src/main/java/com/peernet/test/GetInterfacesGo.java
Normal file
61
app/src/main/java/com/peernet/test/GetInterfacesGo.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
611
app/src/main/java/com/peernet/test/TinyWebServer.java
Normal file
611
app/src/main/java/com/peernet/test/TinyWebServer.java
Normal 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) {
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user