リビジョン | 49 (tree) |
---|---|
日時 | 2009-12-03 00:12:52 |
作者 | hirohitohigashi |
Improvement of robustness
@@ -167,7 +167,7 @@ | ||
167 | 167 | copy_strerror(); |
168 | 168 | return LIBOFTP_ERROR_OS; |
169 | 169 | } |
170 | - DEBUGPRINT1( "RESP1: %s", str1 ); | |
170 | + DEBUGPRINT1( "RESP1: %s\n", str1 ); | |
171 | 171 | if( n < 3 ) { |
172 | 172 | return LIBOFTP_ERROR_PROTOCOL; |
173 | 173 | } |
@@ -185,7 +185,7 @@ | ||
185 | 185 | copy_strerror(); |
186 | 186 | return LIBOFTP_ERROR_OS; |
187 | 187 | } |
188 | - DEBUGPRINT1( "RESP2: %s", str1 ); | |
188 | + DEBUGPRINT1( "RESP2: %s\n", str1 ); | |
189 | 189 | if( n < 3 ) { |
190 | 190 | return LIBOFTP_ERROR_PROTOCOL; |
191 | 191 | } |
@@ -223,7 +223,7 @@ | ||
223 | 223 | */ |
224 | 224 | int ftp_getready_active( LIBOFTP *ftp, const char *cmd, const char *fname ) |
225 | 225 | { |
226 | - int sock = 0; | |
226 | + int sock_listen, sock_accept = -1; | |
227 | 227 | struct sockaddr_in saddr; |
228 | 228 | int saddr_len; |
229 | 229 | unsigned char *ip, *pt; |
@@ -231,6 +231,7 @@ | ||
231 | 231 | int res; |
232 | 232 | struct timeval timeout; |
233 | 233 | fd_set rfds, wfds; |
234 | + int flag_status_ok = 0; | |
234 | 235 | |
235 | 236 | /* |
236 | 237 | * open data port. |
@@ -237,8 +238,8 @@ | ||
237 | 238 | * (note) |
238 | 239 | * same command port ip and automatic random port. |
239 | 240 | */ |
240 | - sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); | |
241 | - if( sock < 0 ) { | |
241 | + sock_listen = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); | |
242 | + if( sock_listen < 0 ) { | |
242 | 243 | DEBUGPRINT1( "getready_active: can't open socket. %s\n", strerror(errno) ); |
243 | 244 | goto ERROR_OS; |
244 | 245 | } |
@@ -251,23 +252,22 @@ | ||
251 | 252 | } |
252 | 253 | saddr.sin_port = htons( 0 ); |
253 | 254 | |
254 | - if( bind( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) { | |
255 | + if( bind( sock_listen, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) { | |
255 | 256 | DEBUGPRINT1( "getready_active: can't bind socket. %s\n", strerror(errno) ); |
256 | 257 | goto ERROR_OS; |
257 | 258 | } |
258 | 259 | |
259 | - if( listen( sock, 1 ) < 0 ) { | |
260 | + if( listen( sock_listen, 1 ) < 0 ) { | |
260 | 261 | DEBUGPRINT1( "getready_active: can't listen socket. %s\n", strerror(errno) ); |
261 | 262 | goto ERROR_OS; |
262 | 263 | } |
263 | 264 | |
264 | - | |
265 | 265 | /* |
266 | 266 | * make PORT command. |
267 | 267 | */ |
268 | 268 | memset( &saddr, 0, sizeof( saddr ) ); |
269 | 269 | saddr_len = sizeof( saddr ); |
270 | - if( getsockname( sock, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) { | |
270 | + if( getsockname( sock_listen, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) { | |
271 | 271 | DEBUGPRINT1( "getready_active: can't get data socket name. %s\n", strerror(errno) ); |
272 | 272 | goto ERROR_OS; |
273 | 273 | } |
@@ -280,13 +280,13 @@ | ||
280 | 280 | */ |
281 | 281 | if( ftp_send_command( ftp, str1 ) < 0 ) { |
282 | 282 | DEBUGPRINT1( "getready_active: %s command sending error.\n", "PORT" ); |
283 | - close( sock ); | |
283 | + close( sock_listen ); | |
284 | 284 | return LIBOFTP_ERROR_OS; |
285 | 285 | } |
286 | 286 | res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); |
287 | 287 | if( res != 200 ) { /* 200: Command okay. */ |
288 | 288 | DEBUGPRINT1( "getready_active: get PORT response code %d\n", res ); |
289 | - close( sock ); | |
289 | + close( sock_listen ); | |
290 | 290 | return LIBOFTP_ERROR_PROTOCOL; |
291 | 291 | } |
292 | 292 |
@@ -300,29 +300,35 @@ | ||
300 | 300 | } |
301 | 301 | if( ftp_send_command( ftp, str1 ) < 0 ) { |
302 | 302 | DEBUGPRINT1( "getready_active: command sending error. %s", str1 ); |
303 | - close( sock ); | |
303 | + close( sock_listen ); | |
304 | 304 | return LIBOFTP_ERROR_OS; |
305 | 305 | } |
306 | 306 | |
307 | 307 | /* |
308 | - * accept data connection with timeout. | |
308 | + * accept data connection with timeout, or get status by control connection. | |
309 | 309 | */ |
310 | 310 | timeout.tv_sec = ftp->timeout_sec; |
311 | 311 | timeout.tv_usec = 0; |
312 | - | |
313 | 312 | do { |
313 | + int nfds = (sock_listen > ftp->socket)? sock_listen: ftp->socket; | |
314 | 314 | FD_ZERO( &rfds ); |
315 | 315 | FD_ZERO( &wfds ); |
316 | - FD_SET( sock, &rfds ); | |
317 | - FD_SET( sock, &wfds ); | |
316 | + if( sock_listen >= 0) { | |
317 | + FD_SET( sock_listen, &rfds ); | |
318 | + FD_SET( sock_listen, &wfds ); | |
319 | + } | |
320 | + FD_SET( ftp->socket, &rfds ); | |
318 | 321 | |
319 | - res = select( sock+1, &rfds, &wfds, 0, &timeout ); | |
320 | - if( res == 0 ) { /* timeout */ | |
322 | + res = select( nfds+1, &rfds, &wfds, 0, &timeout ); | |
323 | + /* ckeck timeout */ | |
324 | + if( res == 0 ) { | |
321 | 325 | DEBUGPRINT1( "getready_active: waiting connection timeout.%s\n", "" ); |
322 | - close( sock ); | |
326 | + close( sock_listen ); | |
323 | 327 | strncpy( ftp->error_message, "connection timeout.", sizeof( ftp->error_message )-1 ); |
324 | 328 | return LIBOFTP_ERROR_TIMEOUT; |
325 | 329 | } |
330 | + | |
331 | + /* check some OS errors. */ | |
326 | 332 | if( res < 0 ) { |
327 | 333 | if( errno == EINTR ) continue; |
328 | 334 | DEBUGPRINT1( "getready_active: select error. %s\n", strerror(errno) ); |
@@ -329,34 +335,39 @@ | ||
329 | 335 | goto ERROR_OS; |
330 | 336 | } |
331 | 337 | |
332 | - if( FD_ISSET( sock, &rfds ) || FD_ISSET( sock, &wfds ) ) break; | |
333 | - } while( 1 ); | |
338 | + /* accept data connection. */ | |
339 | + if( FD_ISSET( sock_listen, &rfds ) || FD_ISSET( sock_listen, &wfds ) ) { | |
340 | + sock_accept = accept( sock_listen, (struct sockaddr *)&saddr, &saddr_len ); | |
341 | + close( sock_listen ); | |
342 | + sock_listen = -1; | |
343 | + if( sock_accept < 0 ) { | |
344 | + DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) ); | |
345 | + goto ERROR_OS; | |
346 | + } | |
347 | + DEBUGPRINT1( "getready_active: socket accept. fd=%d\n", sock_accept ); | |
348 | + } | |
334 | 349 | |
335 | - res = accept( sock, (struct sockaddr *)&saddr, &saddr_len ); | |
336 | - close( sock ); | |
337 | - if( res < 0 ) { | |
338 | - DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) ); | |
339 | - goto ERROR_OS; | |
340 | - } | |
341 | - sock = res; | |
350 | + /* get status. */ | |
351 | + if( FD_ISSET( ftp->socket, &rfds ) ) { | |
352 | + res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); | |
353 | + DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res ); | |
354 | + if( res != 150 ) { /* 150: File status okay; about to open data connection. */ | |
355 | + if( sock_listen >= 0 ) close( sock_listen ); | |
356 | + if( sock_accept >= 0 ) close( sock_accept ); | |
357 | + return LIBOFTP_ERROR_PROTOCOL; | |
358 | + } | |
359 | + flag_status_ok = 1; | |
360 | + } | |
361 | + | |
362 | + } while( !( sock_accept >= 0 && flag_status_ok ) ); | |
342 | 363 | |
343 | - /* | |
344 | - * get status. | |
345 | - */ | |
346 | - res = ftp_receive_response( ftp, ftp->error_message, sizeof(ftp->error_message) - 1 ); | |
347 | - if( res != 150 ) { /* 150: File status okay; about to open data connection. */ | |
348 | - DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res ); | |
349 | - close( sock ); | |
350 | - return LIBOFTP_ERROR_PROTOCOL; | |
351 | - } | |
364 | + return sock_accept; | |
352 | 365 | |
353 | - return sock; | |
354 | - | |
355 | 366 | |
356 | 367 | ERROR_OS: |
357 | 368 | copy_strerror(); |
358 | - if( sock > 0 ) { | |
359 | - close( sock ); | |
369 | + if( sock_listen >= 0 ) { | |
370 | + close( sock_listen ); | |
360 | 371 | } |
361 | 372 | return LIBOFTP_ERROR_OS; |
362 | 373 | } |