1 2 package com.googlecode.android_scripting.facade.wifi; 3 4 import java.io.BufferedInputStream; 5 import java.io.BufferedReader; 6 import java.io.File; 7 import java.io.FileOutputStream; 8 import java.io.IOException; 9 import java.io.InputStream; 10 import java.io.InputStreamReader; 11 import java.io.OutputStream; 12 import java.net.HttpURLConnection; 13 import java.net.ServerSocket; 14 import java.net.Socket; 15 import java.net.SocketException; 16 import java.net.URL; 17 import java.net.UnknownHostException; 18 import java.nio.charset.StandardCharsets; 19 import java.util.HashMap; 20 21 import com.googlecode.android_scripting.Log; 22 import com.googlecode.android_scripting.facade.FacadeManager; 23 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 24 import com.googlecode.android_scripting.rpc.Rpc; 25 import com.googlecode.android_scripting.rpc.RpcParameter; 26 import com.googlecode.android_scripting.rpc.RpcOptional; 27 28 /** 29 * Basic http operations. 30 */ 31 public class HttpFacade extends RpcReceiver { 32 33 private ServerSocket mServerSocket = null; 34 private int mServerTimeout = -1; 35 private HashMap<Integer, Socket> mSockets = null; 36 private int socketCnt = 0; 37 HttpFacade(FacadeManager manager)38 public HttpFacade(FacadeManager manager) throws IOException { 39 super(manager); 40 mSockets = new HashMap<Integer, Socket>(); 41 } 42 inputStreamToOutputStream(InputStream in, OutputStream out)43 private void inputStreamToOutputStream(InputStream in, OutputStream out) throws IOException { 44 if (in == null) { 45 Log.e("InputStream is null."); 46 return; 47 } 48 if (out == null) { 49 Log.e("OutputStream is null."); 50 return; 51 } 52 try { 53 int read = 0; 54 byte[] bytes = new byte[1024]; 55 while ((read = in.read(bytes)) != -1) { 56 out.write(bytes, 0, read); 57 } 58 } catch (IOException e) { 59 e.printStackTrace(); 60 } finally { 61 in.close(); 62 out.close(); 63 } 64 65 } 66 inputStreamToString(InputStream in)67 private String inputStreamToString(InputStream in) throws IOException { 68 BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); 69 StringBuilder sb = new StringBuilder(); 70 String str = null; 71 while ((str = r.readLine()) != null) { 72 sb.append(str); 73 } 74 return sb.toString(); 75 } 76 77 /** 78 * Send an http request and get the response. 79 * 80 * @param url The url to send request to. 81 * @return The HttpURLConnection object. 82 */ httpRequest(String url)83 private HttpURLConnection httpRequest(String url) throws IOException { 84 URL targetURL = new URL(url); 85 HttpURLConnection urlConnection = null; 86 try { 87 urlConnection = (HttpURLConnection) targetURL.openConnection(); 88 urlConnection.connect(); 89 int respCode = urlConnection.getResponseCode(); 90 String respMsg = urlConnection.getResponseMessage(); 91 Log.d("Got response code: " + respCode + " and response msg: " + respMsg); 92 } catch (IOException e) { 93 Log.e("Failed to open a connection to " + url); 94 Log.e(e.toString()); 95 } finally { 96 if (urlConnection != null) { 97 urlConnection.disconnect(); 98 } 99 } 100 return urlConnection; 101 } 102 103 @Rpc(description = "Start waiting for a connection request on a specified port.", 104 returns = "The index of the connection.") httpAcceptConnection(@pcParametername = "port") Integer port)105 public Integer httpAcceptConnection(@RpcParameter(name = "port") Integer port) throws IOException { 106 mServerSocket = new ServerSocket(port); 107 if (mServerTimeout > 0) { 108 mServerSocket.setSoTimeout(mServerTimeout); 109 } 110 Socket sock = mServerSocket.accept(); 111 socketCnt += 1; 112 mSockets.put(socketCnt, sock); 113 return socketCnt; 114 } 115 116 @Rpc(description = "Download a file from specified url.") httpDownloadFile(@pcParametername = "url") String url)117 public void httpDownloadFile(@RpcParameter(name = "url") String url) throws IOException { 118 HttpURLConnection urlConnection = httpRequest(url); 119 String filename = null; 120 String contentDisposition = urlConnection.getHeaderField("Content-Disposition"); 121 // Try to figure out the name of the file being downloaded. 122 // If the server returned a filename, use it. 123 if (contentDisposition != null) { 124 int idx = contentDisposition.toLowerCase().indexOf("filename"); 125 if (idx != -1) { 126 filename = contentDisposition.substring(idx + 9); 127 Log.d("Using name returned by server: " + filename); 128 } 129 } 130 // If the server did not provide a filename to us, use the last part of url. 131 if (filename == null) { 132 int lastIdx = url.lastIndexOf('/'); 133 filename = url.substring(lastIdx + 1); 134 Log.d("Using name from url: " + filename); 135 } 136 InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 137 String outPath = "/sdcard/Download/" + filename; 138 OutputStream output = new FileOutputStream(new File(outPath)); 139 inputStreamToOutputStream(in, output); 140 Log.d("Downloaded file at " + outPath); 141 } 142 143 @Rpc(description = "Make an http request and return the response message.") httpPing(@pcParametername = "url") String url)144 public HttpURLConnection httpPing(@RpcParameter(name = "url") String url) throws IOException { 145 try { 146 HttpURLConnection urlConnection = null; 147 urlConnection = httpRequest(url); 148 return urlConnection; 149 } catch (UnknownHostException e) { 150 return null; 151 } 152 } 153 154 @Rpc(description = "Make an http request and return the response content as a string.") httpRequestString(@pcParametername = "url") String url)155 public String httpRequestString(@RpcParameter(name = "url") String url) throws IOException { 156 HttpURLConnection urlConnection = httpRequest(url); 157 InputStream in = new BufferedInputStream(urlConnection.getInputStream()); 158 String result = inputStreamToString(in); 159 Log.d("Fetched: " + result); 160 return result; 161 } 162 163 @Rpc(description = "Set how many milliseconds to wait for an incoming connection.") httpSetServerTimeout(@pcParametername = "timeout") Integer timeout)164 public void httpSetServerTimeout(@RpcParameter(name = "timeout") Integer timeout) 165 throws SocketException { 166 mServerSocket.setSoTimeout(timeout); 167 mServerTimeout = timeout; 168 } 169 170 @Rpc(description = "Ping to host(URL or IP), return success (true) or fail (false).") 171 // The optional timeout parameter is in unit of second. pingHost(@pcParametername = "host") String hostString, @RpcParameter(name = "timeout") @RpcOptional Integer timeout)172 public Boolean pingHost(@RpcParameter(name = "host") String hostString, 173 @RpcParameter(name = "timeout") @RpcOptional Integer timeout) { 174 try { 175 String host; 176 try { 177 URL url = new URL(hostString); 178 host = url.getHost(); 179 } catch (java.net.MalformedURLException e) { 180 Log.d("hostString is not URL, it may be IP address."); 181 host = hostString; 182 } 183 184 Log.d("Host:" + host); 185 String pingCmdString = "ping -c 1 "; 186 if (timeout != null) { 187 pingCmdString = pingCmdString + "-W " + timeout + " "; 188 } 189 pingCmdString = pingCmdString + host; 190 Log.d("Execute command: " + pingCmdString); 191 Process p1 = java.lang.Runtime.getRuntime().exec(pingCmdString); 192 int returnVal = p1.waitFor(); 193 boolean reachable = (returnVal == 0); 194 Log.d("Ping return Value:" + returnVal); 195 return reachable; 196 } catch (Exception e){ 197 e.printStackTrace(); 198 return false; 199 } 200 /*TODO see b/18899134 for more information. 201 */ 202 } 203 204 @Override shutdown()205 public void shutdown() { 206 for (int key : mSockets.keySet()) { 207 Socket sock = mSockets.get(key); 208 try { 209 sock.close(); 210 } catch (IOException e) { 211 Log.e("Failed to close socket " + key + " on port " + sock.getLocalPort()); 212 e.printStackTrace(); 213 } 214 } 215 } 216 } 217