• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.googlecode.android_scripting.facade.wifi;
18 
19 import com.googlecode.android_scripting.FileUtils;
20 import com.googlecode.android_scripting.Log;
21 import com.googlecode.android_scripting.facade.FacadeManager;
22 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
23 import com.googlecode.android_scripting.rpc.Rpc;
24 import com.googlecode.android_scripting.rpc.RpcOptional;
25 import com.googlecode.android_scripting.rpc.RpcParameter;
26 
27 import java.io.BufferedInputStream;
28 import java.io.BufferedReader;
29 import java.io.File;
30 import java.io.FileOutputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.io.OutputStream;
35 import java.net.HttpURLConnection;
36 import java.net.ServerSocket;
37 import java.net.Socket;
38 import java.net.SocketException;
39 import java.net.URL;
40 import java.net.UnknownHostException;
41 import java.nio.charset.StandardCharsets;
42 import java.util.HashMap;
43 
44 
45 /**
46  * Basic http operations.
47  */
48 public class HttpFacade extends RpcReceiver {
49 
50     private ServerSocket mServerSocket = null;
51     private int mServerTimeout = -1;
52     private HashMap<Integer, Socket> mSockets = null;
53     private int socketCnt = 0;
54 
HttpFacade(FacadeManager manager)55     public HttpFacade(FacadeManager manager) throws IOException {
56         super(manager);
57         mSockets = new HashMap<Integer, Socket>();
58     }
59 
inputStreamToOutputStream(InputStream in, OutputStream out)60     private void inputStreamToOutputStream(InputStream in, OutputStream out) throws IOException {
61         if (in == null) {
62             Log.e("InputStream is null.");
63             return;
64         }
65         if (out == null) {
66             Log.e("OutputStream is null.");
67             return;
68         }
69         try {
70             int read = 0;
71             byte[] bytes = new byte[1024];
72             while ((read = in.read(bytes)) != -1) {
73                 out.write(bytes, 0, read);
74             }
75         } catch (IOException e) {
76             e.printStackTrace();
77         } finally {
78             in.close();
79             out.close();
80         }
81 
82     }
83 
inputStreamToString(InputStream in)84     private String inputStreamToString(InputStream in) throws IOException {
85         BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
86         StringBuilder sb = new StringBuilder();
87         String str = null;
88         while ((str = r.readLine()) != null) {
89             sb.append(str);
90         }
91         r.close();
92         return sb.toString();
93     }
94 
95     /**
96      * Send an http request and get the response.
97      *
98      * @param url The url to send request to.
99      * @return The HttpURLConnection object.
100      */
httpRequest(String url)101     private HttpURLConnection httpRequest(String url) throws IOException {
102         URL targetURL = new URL(url);
103         HttpURLConnection urlConnection = null;
104         try {
105             urlConnection = (HttpURLConnection) targetURL.openConnection();
106             urlConnection.connect();
107             int respCode = urlConnection.getResponseCode();
108             String respMsg = urlConnection.getResponseMessage();
109             Log.d("Got response code: " + respCode + " and response msg: " + respMsg);
110         } catch (IOException e) {
111             Log.e("Failed to open a connection to " + url);
112             Log.e(e.toString());
113         }
114         return urlConnection;
115     }
116 
117     @Rpc(description = "Start waiting for a connection request on a specified port.",
118             returns = "The index of the connection.")
httpAcceptConnection(@pcParametername = "port") Integer port)119     public Integer httpAcceptConnection(@RpcParameter(name = "port") Integer port) throws IOException {
120         mServerSocket = new ServerSocket(port);
121         if (mServerTimeout > 0) {
122             mServerSocket.setSoTimeout(mServerTimeout);
123         }
124         Socket sock = mServerSocket.accept();
125         socketCnt += 1;
126         mSockets.put(socketCnt, sock);
127         return socketCnt;
128     }
129 
130     @Rpc(description = "Download a file from specified url, to an (optionally) specified path.")
httpDownloadFile(@pcParametername = "url") String url, @RpcParameter(name="outPath") @RpcOptional String outPath)131     public void httpDownloadFile(@RpcParameter(name = "url") String url,
132             @RpcParameter(name="outPath") @RpcOptional String outPath) throws IOException {
133         // Create the input stream
134         HttpURLConnection urlConnection = httpRequest(url);
135         // Parse destination path and create the output stream. The function assumes that the path
136         // is specified relative to the system default Download dir.
137         File outFile = FileUtils.getExternalDownload();
138         if (outPath != null && outPath.trim().length() != 0) {
139             // Check to see if the path is absolute.
140             if (outPath.startsWith("/")) {
141                 outFile = new File(outPath);
142             } else {
143                 outFile = new File(outFile, outPath);
144             }
145             // Check to see if specified path should be a dir.
146             if (outPath.endsWith("/")) {
147                 if (!outFile.isDirectory() && !outFile.mkdirs()) {
148                     throw new IOException("Failed to create the path: " + outPath);
149                 }
150             }
151         }
152         // If no filename was specified, use the filename provided by the server.
153         if (outFile.isDirectory()) {
154             String filename = "";
155             String contentDisposition = urlConnection.getHeaderField("Content-Disposition");
156             // Try to figure out the name of the file being downloaded.
157             // If the server returned a filename, use it.
158             if (contentDisposition != null) {
159                 int idx = contentDisposition.toLowerCase().indexOf("filename");
160                 if (idx != -1) {
161                     filename = contentDisposition.substring(idx + 9);
162                     Log.d("Using filename returned by server: " + filename);
163                 }
164             }
165             // If the server did not provide a filename to us, use the last part of url.
166             if (filename.trim().length() == 0) {
167                int lastIdx = url.lastIndexOf('/');
168                 filename = url.substring(lastIdx + 1);
169                 Log.d("Using name from url: " + filename);
170             }
171             outFile = new File(outFile, filename);
172         }
173         InputStream in = new BufferedInputStream(urlConnection.getInputStream());
174         OutputStream output = new FileOutputStream(outFile);
175         inputStreamToOutputStream(in, output);
176         Log.d("Downloaded file from " + url + " to " + outPath);
177         urlConnection.disconnect();
178     }
179 
180     @Rpc(description = "Make an http request and return the response message.")
httpPing(@pcParametername = "url") String url)181     public HttpURLConnection httpPing(@RpcParameter(name = "url") String url) throws IOException {
182         try {
183             HttpURLConnection urlConnection = null;
184             urlConnection = httpRequest(url);
185             urlConnection.disconnect();
186             return urlConnection;
187         } catch (UnknownHostException e) {
188             return null;
189         }
190     }
191 
192     @Rpc(description = "Make an http request and return the response content as a string.")
httpRequestString(@pcParametername = "url") String url)193     public String httpRequestString(@RpcParameter(name = "url") String url) throws IOException {
194         HttpURLConnection urlConnection = httpRequest(url);
195         InputStream in = new BufferedInputStream(urlConnection.getInputStream());
196         String result = inputStreamToString(in);
197         Log.d("Fetched: " + result);
198         urlConnection.disconnect();
199         return result;
200     }
201 
202     @Rpc(description = "Set how many milliseconds to wait for an incoming connection.")
httpSetServerTimeout(@pcParametername = "timeout") Integer timeout)203     public void httpSetServerTimeout(@RpcParameter(name = "timeout") Integer timeout)
204             throws SocketException {
205         mServerSocket.setSoTimeout(timeout);
206         mServerTimeout = timeout;
207     }
208 
209     @Rpc(description = "Ping to host(URL or IP), return success (true) or fail (false).")
210     // The optional timeout parameter is in unit of second.
pingHost(@pcParametername = "host") String hostString, @RpcParameter(name = "timeout") @RpcOptional Integer timeout, @RpcParameter(name = "ping") @RpcOptional String pingType)211     public Boolean pingHost(@RpcParameter(name = "host") String hostString,
212             @RpcParameter(name = "timeout") @RpcOptional Integer timeout,
213             @RpcParameter(name = "ping") @RpcOptional String pingType) {
214         try {
215             String host;
216             try {
217                 URL url = new URL(hostString);
218                 host = url.getHost();
219             } catch (java.net.MalformedURLException e) {
220                 Log.d("hostString is not URL, it may be IP address.");
221                 host = hostString;
222             }
223 
224             Log.d("Host:" + host);
225             String pingCmdString = "ping -c 1 ";
226             if(pingType!=null && pingType.equals("ping6")) {
227                 pingCmdString = "ping6 -c 1 ";
228             }
229             if (timeout != null) {
230                 pingCmdString = pingCmdString + "-W " + timeout + " ";
231             }
232             pingCmdString = pingCmdString + host;
233             Log.d("Execute command: " + pingCmdString);
234             Process p1 = java.lang.Runtime.getRuntime().exec(pingCmdString);
235             int returnVal = p1.waitFor();
236             boolean reachable = (returnVal == 0);
237             Log.d("Ping return Value:" + returnVal);
238             return reachable;
239         } catch (Exception e){
240             e.printStackTrace();
241             return false;
242         }
243         /*TODO see b/18899134 for more information.
244         */
245     }
246 
247     @Override
shutdown()248     public void shutdown() {
249         for (int key : mSockets.keySet()) {
250             Socket sock = mSockets.get(key);
251             try {
252                 sock.close();
253             } catch (IOException e) {
254                 Log.e("Failed to close socket " + key + " on port " + sock.getLocalPort());
255                 e.printStackTrace();
256             }
257         }
258     }
259 }
260