The final version for lede-gui (the phone app for device registration)
[iot2.git] / others / lede-gui / src / main / java / com / example / lede2 / SSH.java
1 /**\r
2  * Created by Tak and Bowon on 17. 7. 21.\r
3  * SSH class can be used to make ssh connections and send command lines\r
4  */\r
5 \r
6 package com.example.lede2;\r
7 \r
8 import android.content.Context;\r
9 import android.util.Log;\r
10 import android.os.AsyncTask;\r
11 import android.widget.TextView;\r
12 \r
13 import com.jcraft.jsch.JSch;\r
14 import com.jcraft.jsch.JSchException;\r
15 import com.jcraft.jsch.Session;\r
16 import com.jcraft.jsch.ChannelExec;\r
17 import com.jcraft.jsch.Channel;\r
18 \r
19 import java.io.IOException;\r
20 import java.io.InputStream;\r
21 import java.lang.String;\r
22 import java.util.ArrayList;\r
23 import java.util.Arrays;\r
24 import java.util.List;\r
25 \r
26 //import android.provider.Settings;\r
27 //import android.support.v7.app.AppCompatActivity;\r
28 //import android.os.Bundle;\r
29 //import java.io.ByteArrayOutputStream;\r
30 //import java.util.Properties;\r
31 //import java.io.PrintStream;\r
32 \r
33 // AsyncTask input : command line\r
34 // AysncTask output : output from a command\r
35 public class SSH extends AsyncTask<String, Void, List<String>> {\r
36 \r
37         // variables used for connection\r
38         private Session session;\r
39         private Channel channel;\r
40         private ChannelExec ce;\r
41         // in this project, we supposed we use fixed host, username, password\r
42         private String host;\r
43         private String username;\r
44         public String password;\r
45         private List<String> result_lines = new ArrayList<String>();\r
46 \r
47         // host, username, password initialize\r
48         @Override\r
49         protected void onPreExecute() {\r
50                 super.onPreExecute();\r
51                 host = ConfigActivity.ROUTERIP;\r
52                 username = ConfigActivity.ROUTERUSER;\r
53                 password = ConfigActivity.RPWD;\r
54 \r
55 \r
56 \r
57 \r
58         }\r
59 \r
60         public void updatePassword(String newPass){\r
61                 password = newPass;\r
62         }\r
63 \r
64         /* \r
65         The functions below are mainly from :\r
66         https://stackoverflow.com/questions/25789245/how-to-get-jsch-shell-command-output-in-string\r
67         */\r
68 \r
69         // open the connection using username, password, and hostname\r
70         public boolean open() throws JSchException {\r
71 \r
72                 JSch jSch = new JSch();\r
73 \r
74                 session = jSch.getSession(username, host, 22);\r
75                 java.util.Properties config = new java.util.Properties();\r
76                 config.put("StrictHostKeyChecking", "no");  // not recommended\r
77                 session.setPassword(password);\r
78                 session.setConfig(config);\r
79 \r
80 \r
81                 Log.d("SSH CONNECT OPEN", "Connecting SSH to " + host + " - Please wait for few seconds... ");\r
82                 session.connect();\r
83                 if (session.isConnected()) {\r
84                         Log.d("SSH CONNECT", "router connected!");\r
85                         return true;\r
86                 } else {\r
87                         Log.d("SSH NOT CONNECT", "router NOT connected!");\r
88                         return false;\r
89                 }\r
90         }\r
91 \r
92         // send a command 1523610518\r
93         public void runCommand(String command) throws JSchException, IOException {\r
94 \r
95                 if (!session.isConnected())\r
96                         throw new RuntimeException("Not connected to an open session.  Call open() first!");\r
97 \r
98                 channel = session.openChannel("exec");\r
99                 ce = (ChannelExec) channel;\r
100                 ce.setCommand(command);\r
101                 ce.connect();\r
102                 Log.d("SSH RUN COMMAND", command);\r
103         }\r
104 \r
105         // get output from a command\r
106         private List<String> getChannelOutput(Channel channel) throws IOException {\r
107 \r
108                 byte[] buffer = new byte[2048];\r
109                 List<String> output_lines = new ArrayList<String>();\r
110                 try {\r
111                         InputStream in = channel.getInputStream();\r
112                         String line = new String();\r
113                         while (true) {\r
114                                 while (in.available() > 0) {\r
115                                         int i = in.read(buffer, 0, 2048);\r
116                                         if (i < 0) {\r
117                                                 break;\r
118                                         }\r
119                                         line = new String(buffer, 0, i);\r
120                                         // add the read line to the return value list.\r
121                                         output_lines = new ArrayList(Arrays.asList(line.split("\\n")));\r
122                                 }\r
123 \r
124                                 if(line.contains("logout")) {\r
125                                         break;\r
126                                 }\r
127                                 if (channel.isClosed()) {\r
128                                         break;\r
129                                 }\r
130                                 try {\r
131                                         Thread.sleep(1000);\r
132                                 } catch (Exception ee){}\r
133                         }\r
134                 } catch(Exception e) {\r
135                         Log.d("SSH READOUTPUT ERROR", "Error while reading channel output: "+ e);\r
136                 }\r
137 \r
138                 return output_lines;\r
139         }\r
140 \r
141 \r
142         /*\r
143         usage :\r
144         0. params == "-ch <password>" : change default password into <password>\r
145         1. params == "-co <password>" : add device to the database and hostapd file\r
146         2. params == "-dn <password>" : delete devices by their names\r
147         3. params == "-ln <password>" : list devices' names\r
148         */\r
149         @Override\r
150         protected List<String> doInBackground(String... params) {\r
151 \r
152                 List<String> output = new ArrayList<String>();\r
153                 String cmd;\r
154 \r
155                 if(params[0].substring(0,3).equals("-ch")) { // ./change_default_pw.sh -ch <password>\r
156                         cmd = MainActivity.DEF_CHANGE_DEFAULT_SCRIPT + " " + params[0];\r
157                 } else if(params[0].substring(0,3).equals("-co")) { // ./connect_device.sh -co <password> <device-name>\r
158                         cmd = MainActivity.DEF_CONNECT_DEVICE_SCRIPT + " " + params[0];\r
159                 } else if(params[0].substring(0,3).equals("-dn")) { // ./register_device.sh -dn <device-name>\r
160                         cmd = MainActivity.DEF_REGISTER_DEVICE_SCRIPT + " " + params[0];\r
161                 } else if(params[0].substring(0,3).equals("-ln")) { // ./register_device.sh -ln <device-name>\r
162                         // below block is a little different from others cause it needs to get output from the router\r
163                         try {\r
164                                 // try open the connection\r
165                                 if (!open()) {\r
166                                         Log.d("SSH CONNECTION CLOSE", "open failed.");\r
167                                         return null;\r
168                                 }\r
169                                 cmd = MainActivity.DEF_REGISTER_DEVICE_SCRIPT + " " + params[0];\r
170                                 System.out.println(cmd);\r
171                                 runCommand(cmd);\r
172                                 ce.setCommand(cmd);\r
173                                 ce.connect();\r
174                                 result_lines = getChannelOutput(ce);\r
175                                 //output = getChannelOutput(ce);\r
176                         } catch (Exception e) {\r
177                         }\r
178                         channel.disconnect();\r
179 \r
180                         // only this block return meaningful value, which should be the names of devices.\r
181                         return output;\r
182                 } else if(params[0].substring(0,3).equals("cat")) {\r
183                         cmd = params[0];\r
184                 }\r
185                 else if(params[0].substring(0,4).equals("echo")) {\r
186                         cmd = params[0];\r
187                 }\r
188                 else {\r
189                         Log.d("SSH PARAM ERROR", "Wrong parameter used.");\r
190                         return null;\r
191                 }\r
192 \r
193                 // now the command is set, so send it.\r
194                 try {\r
195                         // try open the connection\r
196                         if (!open()) {\r
197                                 Log.d("SSH CONNECTION CLOSE", "open failed.");\r
198                                 return null;\r
199                         }\r
200                         System.out.println(cmd);\r
201                         runCommand(cmd);\r
202                         ce.setCommand(cmd);\r
203                         ce.connect();\r
204                         result_lines = getChannelOutput(ce);\r
205                 } catch (Exception e) {\r
206                 } // done\r
207 \r
208                 channel.disconnect();\r
209                 return null;\r
210         }\r
211 \r
212         public List<String> getResultLines() {\r
213                 return result_lines;\r
214         }\r
215 \r
216         /*\r
217         @Override\r
218         protected  onPostExecute(Void param) {\r
219                 Log.d("POST", "in post execute");\r
220         }\r
221         */\r
222 }\r