A. M. Anisul Huq Posted July 19, 2012 Share Posted July 19, 2012 I am building a Proxy Server for android and I have hit a wall. I need help desperately. I am quite new to Android. So, at first, I made the Proxy server in Java SE. The Proxy Server works as following: It listens to a local port, When the client connects, a new thread is created. Each thread is also given a name. The HOST is extracted from the request. Client's request is then forwarded to the Remote address (acquired from HOST). The Proxy then reads the remote server's address until -1 is found. This response is then forwarded to the client. The proxy server is run in the Laptop. The client is Youtube APP of an android phone. The phone is rooted and I have installed ProxyDroid to tell the client where the Proxy Server is. "Global Proxy" option of ProxyDroid is used. The code in Java SE: import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.ServerSocket; import java.net.Socket; import java.util.Enumeration; class clientThread implements Runnable { Socket clientSocket = null;//each client socket. Socket connectYoutubeServerSock = null;//This socket is used to write client's request to the //YouTube Server. int videoFlag = 0;//this flag determines whether the GET request is a video request or not. final int BufferSize = 8019; public String hostURL; int youtubePort = 80; //public DataOutputStream sendClientResponse = null; public clientThread(Socket clientSocket) { this.clientSocket = clientSocket; } public void run() { System.out.println("Client connected: "+clientSocket.toString()); System.out.println("Current Thread Name: "+Thread.currentThread().getName()); try { byte youtubeAppReqArray[] = new byte[bufferSize];//this byte array will house youtube app's request! InputStream youtubeAppReq = clientSocket.getInputStream(); // reading the request and put it into youtubeAppReqArray. int bytesRead = youtubeAppReq.read(youtubeAppReqArray,0,BufferSize); String youtubeAppReqString = new String(youtubeAppReqArray, 0, bytesRead); System.out.println(youtubeAppReqString); // extract the url of the GET request! int gStart = youtubeAppReqString.indexOf("GET: ") + 4; int gEnd = youtubeAppReqString.indexOf('\n', gStart); String gURL = youtubeAppReqString.substring(gStart, gEnd - 9); System.out.println("URL of GET: " + gURL); //test if videoplayback is there or not? if(gURL.indexOf("videoplayback") > -1 ) { System.out.println("This is a video request!"); videoFlag = 1; } // extract the host to connect to int hStart = youtubeAppReqString.indexOf("Host: ") + 6; int hEnd = youtubeAppReqString.indexOf('\n', hStart); String host = youtubeAppReqString.substring(hStart, hEnd - 1); System.out.println("Connecting to host " + host); //forward the youtube app request from proxy to the youtube server Socket youtubeServerSocket = new Socket(host, 80); OutputStream writeToYoutubeServerStream = youtubeServerSocket.getOutputStream(); System.out.println("Forwarding request to server"); writeToYoutubeServerStream.write(youtubeAppReqArray, 0, bytesRead); writeToYoutubeServerStream.flush(); // forward the response from the server to the browser byte youtubeServerResArray[] = new byte[bufferSize];//this byte array will house youtube server's response. InputStream readFromYoutubeServerStream = youtubeServerSocket.getInputStream(); OutputStream writeToYoutubeAppStream = clientSocket.getOutputStream(); System.out.println("Forwarding request from server"); int remoteBytesRead; do { remoteBytesRead = readFromYoutubeServerStream.read(youtubeServerResArray,0,BufferSize); System.out.println("Receiving " + remoteBytesRead + " bytes"); if (remoteBytesRead > 0) { writeToYoutubeAppStream.write(youtubeServerResArray, 0, remoteBytesRead); String rData = new String(youtubeServerResArray,0,remoteBytesRead); System.out.println("Remote data: "+rData); } } while (remoteBytesRead > 0); writeToYoutubeAppStream.flush(); youtubeServerSocket.close(); clientSocket.close(); System.out.println("End of communication"); } catch(IOException ioe) { System.out.println("Error"+ioe.getMessage()); } } } public class ChallengeProxy extends IOException { public static final int SERVERPORT = 4447; public static int threadName = 0; public static void main(String[] args) { ChallengeProxy proxyObj = new ChallengeProxy(); proxyObj.knowIP();//get the IP address of the local machine! try { ServerSocket serverSocket = new ServerSocket(SERVERPORT); System.out.println("Started on: "+SERVERPORT); while(true)//Non stop listen for clients! { Socket clientSocket = serverSocket.accept();//blocks until client is connected! System.out.println("Client connected: "+clientSocket.toString()); Thread t = new Thread(new clientThread(clientSocket), Integer.toString(threadName)); t.start(); threadName++; } } catch (IOException ioe) { System.out.println("Could not listen on port: "+SERVERPORT); System.out.println("Error"+ioe.getMessage()); } catch(Exception e) { System.out.println("Error"+e.getMessage()); } } public void knowIP() { //This method just gets IP address of the native machine. } } It does is exactly what I want. Now, I transform the code a little, so that, it runs in Android. However, the logic underneath is the same. Here also, when a new client connects, a new thread is created. The Youtube APP is still the client. So now, the YouTube APP would request a proxy server residing in the same Android machine. As before, ProxyDroid is configured so that, YouTube APP knows where my Proxy server is running. The code for Android looks like (the code is not complete, because before compliting it has started showing serious errors!): public class ChallengeAndroidProxyActivity extends Activity { public static final int SERVERPORT = 4453; public static int threadName = 0; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); (new Thread(new Runnable() { public void run() { startSocketServer(); } } )).start(); } /* * Here we will create an infinite loop that will listen * for client connections. * * */ public void startSocketServer() { knowIP();// Now we find the IP address of the native machine. String LOG_TAG = "SocketServerThread"; Log.i(LOG_TAG,"Inside the server thread! "); try { ServerSocket serverSocket = new ServerSocket(SERVERPORT); Log.i(LOG_TAG, "Started on : " + SERVERPORT); threadName = 0; while (true)// Non stop listen for clients! { Socket clientSocket = serverSocket.accept(); Log.d(LOG_TAG , "Client connected : " + clientSocket.toString()); Thread t = new Thread(new clientThread(clientSocket), Integer.toString(threadName)); t.start(); threadName++; } } catch (IOException ioe) { Log.i(LOG_TAG, "Could not listen on port: " + SERVERPORT); Log.i(LOG_TAG, "Error : " + ioe.getMessage()); } catch (Exception e) { Log.i(LOG_TAG, "Error : " + e.getMessage()); } } class clientThread implements Runnable { String LOG_TAG = "clientSocketThread"; Socket clientSocket = null;//each client socket. Socket connectYoutubeServerSock = null;//This socket is used to write client's request to the //YouTube Server. int videoFlag = 0;//this flag determines whether the GET request is a video request or not. final int BufferSize = 8019; public String hostURL; int youtubePort = 80; public clientThread(Socket clientSocket) { this.clientSocket = clientSocket; } public void run() { Log.i(LOG_TAG,"Client connected: "+clientSocket.toString()); Log.i(LOG_TAG,"Current Thread Name: "+Thread.currentThread().getName()); try {//1 byte youtubeAppReqArray[] = new byte[bufferSize];//this byte array will house youtube app's request! InputStream youtubeAppReq = clientSocket.getInputStream(); // reading the request and put it into youtubeAppReqArray. int bytesRead = youtubeAppReq.read(youtubeAppReqArray,0,BufferSize); String youtubeAppReqString = new String(youtubeAppReqArray, 0, bytesRead); Log.i("Youtube App Request: ",youtubeAppReqString); // extract the host to connect to int hStart = youtubeAppReqString.indexOf("Host: ") + 6; int hEnd = youtubeAppReqString.indexOf('\n', hStart); String host = youtubeAppReqString.substring(hStart, hEnd - 1); Log.i("Connecting to host ",host); InetAddress addr = InetAddress.getByName(host); int port = 80; SocketAddress sockaddr = new InetSocketAddress(addr, port); Socket youtubeServerSocket = new Socket(); youtubeServerSocket.connect(sockaddr); OutputStream writeToYoutubeServerStream = youtubeServerSocket.getOutputStream(); //writeToYoutubeServerStream.write(youtubeAppReqArray, 0, bytesRead); }//1 catch(IOException ioe) {//1 Log.i("Error",ioe.getMessage()); }//1 } } /************************************************************************************/ public void knowIP() { This function just gets the IP of the native machine. } } The code has been modified according to the changes suggested by the first answer. When the line of code //writeToYoutubeServerStream.write(youtubeAppReqArray, 0, bytesRead); is commented out (by this line, my proxy writes client's request to the Remote server), the request that I get from the client looks like: 07-19 22:30:16.309: I/ApplicationPackageManager(2843): cscCountry is not German : NEE 07-19 22:30:16.399: I/Net interface:(2843): wlan0 07-19 22:30:16.429: I/IP address:(2843): /192.168.1.129 07-19 22:30:16.429: I/Net interface:(2843): lo 07-19 22:30:16.439: I/IP address:(2843): /127.0.0.1 07-19 22:30:16.439: I/SocketServerThread(2843): Inside the server thread! 07-19 22:30:16.439: I/SocketServerThread(2843): Started on : 4453 07-19 22:30:20.929: D/SocketServerThread(2843): Client connected : Socket[addr=/192.168.1.129,port=44276,localport=4453] 07-19 22:30:20.959: I/clientSocketThread(2843): Client connected: Socket[addr=/192.168.1.129,port=44276,localport=4453] 07-19 22:30:20.959: I/clientSocketThread(2843): Current Thread Name: 0 07-19 22:30:20.969: I/Youtube App Request:(2843): GET http://gdata.youtube.com/feeds/api/users/asadfffx/newsubscriptionvideos?format=2%2C3%2C9&start-index=1&max-results=10&safeSearch=none HTTP/1.1 07-19 22:30:20.969: I/Youtube App Request:(2843): GData-Version: 2 07-19 22:30:20.969: I/Youtube App Request:(2843): X-GData-Device: device-id="AOuj_RqmoX-WkCNNaJKieF2mmwMlkOMFRk7sQsKP_wmdrL1BB1N9V_iVIJAUBkvvyzGdpxWVS83wE7UkGPYjWf0BWvbPa0Uoo0cmgKfxzEqOog8EC-Rm1Wg", data="H1NEdDZ+FuL4U9v3Bx1hlVIAm1s=" 07-19 22:30:20.969: I/Youtube App Request:(2843): Authorization: GoogleLogin auth="DQAAAKcAAAC5aU6IN0t6yUkoiU9OmjU8fYjKm1m7MLKleHLhtR-uwCclnZGcKGm-6gYfkjvAGKGXK88dbKnB708CVCQkvJofL6smBXp7TEFj1FqGaRasdOx2iVYrbaTbWtIc8sBaga7v2P1BfctMiSTtEU2HWCqqCiubMvpfspnl9wS284SLgk-Se4jjFsZTo-84la_2wJy_Wmap8OSTdif7JoaxpxYLAWECByrJO50iMTj__6cN3A" 07-19 22:30:20.969: I/Youtube App Request:(2843): Host: gdata.youtube.com 07-19 22:30:20.969: I/Youtube App Request:(2843): User-Agent: Android-YouTube/2 07-19 22:30:20.969: I/Youtube App Request:(2843): Proxy-Connection: close 07-19 22:30:20.969: I/Youtube App Request:(2843): Connection: close 07-19 22:30:20.969: I/Youtube App Request:(2843): 07-19 22:30:20.979: I/Connecting to host(2843): gdata.youtube.com This is how the client's request should look like. But when I un-comment the following line (i.e. it gets executed): writeToYoutubeServerStream.write(youtubeAppReqArray, 0, bytesRead); everything falls apart. Specially, the request from the YouTube App does not make any sense. Hundreds of threads get created. And my GET request starts to look like: 07-19 22:36:21.969: I/Youtube App Request:(2916): GData-Version: 2 07-19 22:36:21.969: I/Youtube App Request:(2916): X-GData-Device: device-id="AOuj_RqmoX-WkCNNaJKieF2mmwMlkOMFRk7sQsKP_wmdrL1BB1N9V_iVIJAUBkvvyzGdpxWVS83wE7UkGPYjWf0BWvbPa0Uoo0cmgKfxzEqOog8EC-Rm1Wg", data="H1NEdDZ+FuL4U9v3Bx1hlVIAm1s=" 07-19 22:36:21.969: I/Youtube App Request:(2916): Authorization: GoogleLogin auth="DQAAAKcAAAC5aU6IN0t6yUkoiU9OmjU8fYjKm1m7MLKleHLhtR-uwCclnZGcKGm-6gYfkjvAGKGXK88dbKnB708CVCQkvJofL6smBXp7TEFj1FqGaRasdOx2iVYrbaTbWtIc8sBaga7v2P1BfctMiSTtEU2HWCqqCiubMvpfspnl9wS284SLgk-Se4jjFsZTo-84la_2wJy_Wmap8OSTdif7JoaxpxYLAWECByrJO50iMTj__6cN3A" 07-19 22:36:21.969: I/Youtube App Request:(2916): Host: gdat 07-19 22:36:21.969: I/Connecting to host(2916): gdata.youtube.com 07-19 22:36:21.979: D/SocketServerThread(2916): Client connected : Socket[addr=/192.168.1.129,port=55126,localport=4453] 07-19 22:36:21.979: I/clientSocketThread(2916): Client connected: Socket[addr=/192.168.1.129,port=55125,localport=4453] 07-19 22:36:21.979: I/clientSocketThread(2916): Current Thread Name: 463 07-19 22:36:21.979: I/Youtube App Request:(2916): GET http://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.comhttp://gdata.youtube.com/feeds/api/users/asadfffx/newsubscriptionvideos?format=2%2C3%2C9&start-index=1&max-results=10&safeSearch=none HTTP/1.1 07-19 22:36:21.979: I/Youtube App Request:(2916): GData-Version: 2 07-19 22:36:21.979: I/Youtube App Request:(2916): X-GData-Device: device-id="AOuj_RqmoX-WkCNNaJKieF2mmwMlkOMFRk7sQsKP_wmdrL1BB1N9V_iVIJAUBkvvyzGdpxWVS83wE7UkGPYjWf0BWvbPa0Uoo0cmgKfxzEqOog8EC-Rm1Wg", data="H1NEdDZ+FuL4U9v3Bx1hlVIAm1s=" 07-19 22:36:21.979: I/Youtube App Request:(2916): Authorization: GoogleLogin auth="DQAAAKcAAAC5aU6IN0t6yUkoiU9OmjU8fYjKm1m7MLKleHLhtR-uwCclnZGcKGm-6gYfkjvAGKGXK88dbKnB708CVCQkvJofL6smBXp7TEFj1FqGaRasdOx2iVYrbaTbWtIc8sBaga7v2P1BfctMiSTtEU2HWCqqCiubMvpfspnl9wS284SLgk-Se4jjFsZTo-84la_2wJy_Wmap8OSTdif7JoaxpxYLAWECByrJO50iMTj__6cN3A" 07-19 22:36:21.979: I/Youtube App Request:(2916): Host: gdata.youtube.com Why does the GET request look like this? My guess is that, something is wrong with the threads. Is creating socket, read/write thread safe? Is the code jumping between threads? What am I doing wrong? The same code works in Java SE; so why does it fall apart in Android? Any suggestions, comments and code snippet will be appreciated. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.