1
1
package cc .arduino .packages .uploaders ;
2
2
3
3
import cc .arduino .packages .Uploader ;
4
- import com .jcraft .jsch .*;
4
+ import cc .arduino .packages .uploaders .ssh .SCP ;
5
+ import cc .arduino .packages .uploaders .ssh .SSH ;
6
+ import com .jcraft .jsch .JSch ;
7
+ import com .jcraft .jsch .JSchException ;
8
+ import com .jcraft .jsch .Session ;
5
9
import processing .app .Base ;
6
10
import processing .app .Constants ;
7
11
import processing .app .NetworkMonitor ;
8
12
import processing .app .Preferences ;
9
13
import processing .app .debug .RunnerException ;
10
14
import processing .app .debug .TargetPlatform ;
11
- import processing .app .helpers .FileUtils ;
12
15
import processing .app .helpers .PreferencesMap ;
13
16
14
- import java .io .*;
17
+ import java .io .File ;
18
+ import java .io .IOException ;
15
19
import java .util .regex .Matcher ;
16
20
17
21
import static processing .app .I18n ._ ;
@@ -44,6 +48,7 @@ public boolean uploadUsingPreferences(File sourcePath, String buildPath, String
44
48
}
45
49
46
50
Session session = null ;
51
+ SCP scp = null ;
47
52
try {
48
53
JSch jSch = new JSch ();
49
54
session = jSch .getSession ("root" , ipAddress , 22 );
@@ -52,24 +57,12 @@ public boolean uploadUsingPreferences(File sourcePath, String buildPath, String
52
57
session .setUserInfo (new NetworkMonitor .NoInteractionUserInfo ());
53
58
session .connect (30000 );
54
59
55
- SCP scp = new SCP (session );
60
+ scp = new SCP (session );
56
61
SSH ssh = new SSH (session );
57
62
58
- File www = new File (sourcePath , "www" );
59
- if (www .exists () && www .isDirectory () && www .canExecute () && canUploadWebFiles (ssh )) {
60
- File destination = new File ("/www/sd/" + www .getParentFile ().getName ());
61
- ssh .execSyncCommand ("mkdir -p " + FileUtils .getLinuxPathFrom (destination ), System .out );
62
- copyWebFiles (scp , ssh , www , destination );
63
- }
64
-
65
- String uploadedSketchFile = scp .scpHexToBoard (buildPath , className );
66
-
67
- TargetPlatform targetPlatform = Base .getTargetPlatform ();
68
- PreferencesMap prefs = Preferences .getMap ();
69
- prefs .putAll (Base .getBoardPreferences ());
70
- prefs .putAll (targetPlatform .getTool (prefs .get ("upload.tool" )));
63
+ scpFiles (scp , ssh , sourcePath , buildPath , className , session );
71
64
72
- return new SSHAVRDude ( session ). runAVRDude (uploadedSketchFile , verbose ? prefs . get ( "upload.params.verbose" ) : prefs . get ( "upload.params.quiet" ) );
65
+ return runAVRDude (ssh );
73
66
} catch (JSchException e ) {
74
67
if ("Auth cancel" .equals (e .getMessage ())) {
75
68
return false ;
@@ -78,228 +71,90 @@ public boolean uploadUsingPreferences(File sourcePath, String buildPath, String
78
71
} catch (Exception e ) {
79
72
throw new RunnerException (e );
80
73
} finally {
74
+ if (scp != null ) {
75
+ try {
76
+ scp .close ();
77
+ } catch (IOException e ) {
78
+ throw new RunnerException (e );
79
+ }
80
+ }
81
81
if (session != null ) {
82
82
session .disconnect ();
83
83
}
84
84
}
85
85
}
86
86
87
- private void copyWebFiles (SCP scp , SSH ssh , File from , File destination ) throws IOException , JSchException {
88
- File [] files = from .listFiles ();
89
- if (files == null ) {
90
- throw new IOException ("Cannot list files in " + from );
91
- }
92
- for (File file : files ) {
93
- if (file .isDirectory () && file .canExecute ()) {
94
- File newDestination = new File (destination , file .getName ());
95
- ssh .execSyncCommand ("mkdir -p " + FileUtils .getLinuxPathFrom (newDestination ), System .out );
96
- copyWebFiles (scp , ssh , file , newDestination );
97
- } else {
98
- scp .scpFile (file , FileUtils .getLinuxPathFrom (new File (destination , file .getName ())));
99
- }
100
- }
101
- }
87
+ private boolean runAVRDude (SSH ssh ) throws IOException , JSchException {
88
+ TargetPlatform targetPlatform = Base .getTargetPlatform ();
89
+ PreferencesMap prefs = Preferences .getMap ();
90
+ prefs .putAll (Base .getBoardPreferences ());
91
+ prefs .putAll (targetPlatform .getTool (prefs .get ("upload.tool" )));
102
92
103
- private boolean canUploadWebFiles (SSH ssh ) throws JSchException , IOException {
104
- ByteArrayOutputStream baos = new ByteArrayOutputStream ();
105
- PrintStream ps = new PrintStream (baos );
106
- ssh .execSyncCommand ("if [ -L /www/sd ] && [ -d /www/sd ]; then echo 1; else echo 0; fi" , ps );
107
- String output = new String (baos .toByteArray ());
108
- return "1" .equals (output .trim ());
109
- }
93
+ String additionalParams = verbose ? prefs .get ("upload.params.verbose" ) : prefs .get ("upload.params.quiet" );
110
94
111
- @ Override
112
- public boolean burnBootloader () throws RunnerException {
113
- throw new RunnerException ("Can't burn bootloader via SSH" );
95
+ boolean success = ssh .execSyncCommand ("merge-sketch-with-bootloader /tmp/sketch.hex" , System .out , System .err );
96
+ ssh .execSyncCommand ("kill-bridge" );
97
+ success = success && ssh .execSyncCommand ("run-avrdude /tmp/sketch.hex '" + additionalParams + "'" , System .out , System .err );
98
+ return success ;
114
99
}
115
100
116
- private static class SSH {
117
-
118
- protected final Session session ;
119
-
120
- public SSH (Session session ) {
121
- this .session = session ;
122
- }
123
-
124
- protected boolean execSyncCommand (String command , PrintStream stdoutConsumer ) throws JSchException , IOException {
125
- return execSyncCommand (command , stdoutConsumer , null );
126
- }
127
-
128
- protected boolean execSyncCommand (String command , PrintStream stdoutConsumer , PrintStream stderrConsumer ) throws JSchException , IOException {
129
- InputStream stdout = null ;
130
- InputStream stderr = null ;
131
- Channel channel = null ;
132
- try {
133
- channel = session .openChannel ("exec" );
134
- ((ChannelExec ) channel ).setCommand (command );
135
-
136
- channel .setInputStream (null );
137
-
138
- stdout = channel .getInputStream ();
139
- if (stderrConsumer != null ) {
140
- stderr = ((ChannelExec ) channel ).getErrStream ();
141
- }
142
-
143
- channel .connect ();
144
-
145
- int exitCode = consumeOutputSyncAndReturnExitCode (channel , stdout , stdoutConsumer , stderr , stderrConsumer );
146
-
147
- return stderrConsumer == null || exitCode == 0 ;
148
-
149
- } finally {
150
- if (stdout != null ) {
151
- stdout .close ();
152
- }
153
- if (stderr != null ) {
154
- stderr .close ();
155
- }
156
- if (channel != null ) {
157
- channel .disconnect ();
158
- }
159
- }
160
- }
161
-
162
- protected int consumeOutputSyncAndReturnExitCode (Channel channel , InputStream stdout , PrintStream stdoutConsumer , InputStream stderr , PrintStream stderrConsumer ) throws IOException {
163
- byte [] tmp = new byte [102400 ];
164
- while (true ) {
165
- consumeStream (tmp , stdout , stdoutConsumer );
166
- consumeStream (tmp , stderr , stderrConsumer );
167
-
168
- if (channel .isClosed ()) {
169
- return channel .getExitStatus ();
170
- }
171
- try {
172
- Thread .sleep (100 );
173
- } catch (Exception ee ) {
174
- // noop
175
- }
176
- }
177
- }
178
-
179
- private void consumeStream (byte [] buffer , InputStream in , PrintStream out ) throws IOException {
180
- while (in != null && in .available () > 0 ) {
181
- int length = in .read (buffer , 0 , buffer .length );
182
- if (length < 0 ) {
183
- break ;
184
- }
185
- out .print (new String (buffer , 0 , length ));
101
+ private void scpFiles (SCP scp , SSH ssh , File sourcePath , String buildPath , String className , Session session ) throws JSchException , IOException {
102
+ try {
103
+ scp .open ();
104
+ scp .startFolder ("tmp" );
105
+ scp .sendFile (new File (buildPath , className + ".hex" ), "sketch.hex" );
106
+ scp .endFolder ();
107
+
108
+ if (canUploadWWWFiles (sourcePath , ssh )) {
109
+ scp .startFolder ("www" );
110
+ scp .startFolder ("sd" );
111
+ scp .startFolder (sourcePath .getName ());
112
+ recursiveSCP (new File (sourcePath , "www" ), scp );
113
+ scp .endFolder ();
114
+ scp .endFolder ();
115
+ scp .endFolder ();
186
116
}
117
+ } finally {
118
+ scp .close ();
187
119
}
188
-
189
- }
190
-
191
- private static class SSHAVRDude extends SSH {
192
-
193
- public SSHAVRDude (Session session ) {
194
- super (session );
195
- }
196
-
197
- public boolean runAVRDude (String sketchFile , String additionalParams ) throws IOException , JSchException {
198
- boolean success = execSyncCommand ("merge-sketch-with-bootloader " + sketchFile , System .out , System .err );
199
- success = success && execSyncCommand ("kill-bridge" , System .out );
200
- success = success && execSyncCommand ("run-avrdude " + sketchFile + " '" + additionalParams + "'" , System .out , System .err );
201
- return success ;
202
- }
203
-
204
120
}
205
121
206
- private static class SCP extends SSH {
207
-
208
- private static final String SKETCH_FILE = "/tmp/sketch.hex" ;
209
-
210
- public SCP (Session session ) {
211
- super (session );
122
+ private boolean canUploadWWWFiles (File sourcePath , SSH ssh ) throws IOException , JSchException {
123
+ File www = new File (sourcePath , "www" );
124
+ if (!www .exists () || !www .isDirectory ()) {
125
+ return false ;
212
126
}
213
-
214
- public void scpFile (File from , String absolutePathToDestination ) throws JSchException , IOException {
215
- Channel channel = null ;
216
- OutputStream out = null ;
217
- InputStream in = null ;
218
- try {
219
- channel = session .openChannel ("exec" );
220
- ((ChannelExec ) channel ).setCommand ("scp -t " + absolutePathToDestination );
221
-
222
- out = channel .getOutputStream ();
223
- in = channel .getInputStream ();
224
-
225
- channel .connect ();
226
-
227
- ensureAcknowledged (out , in );
228
-
229
- sendFileSizeAndName (out , in , from );
230
- ensureAcknowledged (out , in );
231
-
232
- sendFileContents (out , from );
233
- ensureAcknowledged (out , in );
234
- } finally {
235
- if (out != null ) {
236
- out .close ();
237
- }
238
- if (in != null ) {
239
- in .close ();
240
- }
241
- if (channel != null ) {
242
- channel .disconnect ();
243
- }
244
- }
127
+ if (!www .canExecute ()) {
128
+ System .out .println ("Problem accessing files in folder " + www );
129
+ return false ;
245
130
}
246
-
247
- public String scpHexToBoard (String buildPath , String className ) throws JSchException , IOException {
248
- scpFile (new File (buildPath , className + ".hex" ), SKETCH_FILE );
249
- return SKETCH_FILE ;
131
+ if (!ssh .execSyncCommand ("special-storage-available" )) {
132
+ System .out .println ("Problem accessing board folder /www/sd" );
133
+ return false ;
250
134
}
135
+ return true ;
136
+ }
251
137
252
- private void ensureAcknowledged (OutputStream out , InputStream in ) throws IOException {
253
- out .flush ();
254
-
255
- int b = in .read ();
256
-
257
- if (b == 0 ) return ;
258
- if (b == -1 ) return ;
259
-
260
- if (b == 1 || b == 2 ) {
261
- StringBuilder sb = new StringBuilder ();
262
- sb .append ("SCP error: " );
263
-
264
- int c ;
265
- do {
266
- c = in .read ();
267
- sb .append ((char ) c );
268
- } while (c != '\n' );
269
-
270
- throw new IOException (sb .toString ());
271
- }
272
-
273
- throw new IOException ("Uknown SCP error: " + b );
138
+ private void recursiveSCP (File from , SCP scp ) throws IOException {
139
+ File [] files = from .listFiles ();
140
+ if (files == null ) {
141
+ return ;
274
142
}
275
143
276
- private void sendFileContents (OutputStream out , File hex ) throws IOException {
277
- FileInputStream fis = null ;
278
- try {
279
- fis = new FileInputStream (hex );
280
- byte [] buf = new byte [4096 ];
281
- while (true ) {
282
- int len = fis .read (buf , 0 , buf .length );
283
- if (len <= 0 ) break ;
284
- out .write (buf , 0 , len );
285
- }
286
-
287
- // \0 terminates file
288
- buf [0 ] = 0 ;
289
- out .write (buf , 0 , 1 );
290
- } finally {
291
- if (fis != null ) {
292
- fis .close ();
293
- }
144
+ for (File file : files ) {
145
+ if (file .isDirectory () && file .canExecute ()) {
146
+ scp .startFolder (file .getName ());
147
+ recursiveSCP (file , scp );
148
+ scp .endFolder ();
149
+ } else if (file .isFile () && file .canRead ()) {
150
+ scp .sendFile (file );
294
151
}
295
152
}
153
+ }
296
154
297
- private void sendFileSizeAndName (OutputStream out , InputStream in , File hex ) throws IOException {
298
- long filesize = hex .length ();
299
- String command = "C0644 " + filesize + " " + hex .getName () + "\n " ;
300
- out .write (command .getBytes ());
301
- }
302
-
155
+ @ Override
156
+ public boolean burnBootloader () throws RunnerException {
157
+ throw new RunnerException ("Can't burn bootloader via SSH" );
303
158
}
304
159
305
160
}
0 commit comments