diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/clientloop.c b/clientloop.c index af207c070..9549dadd4 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -317,10 +317,14 @@ client_check_window_change(void) | |||
317 | * one of the file descriptors). | 317 | * one of the file descriptors). |
318 | */ | 318 | */ |
319 | 319 | ||
320 | static void | 320 | static int |
321 | client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | 321 | client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, |
322 | int *maxfdp, int *nallocp, int rekeying) | 322 | int *maxfdp, int *nallocp, int rekeying) |
323 | { | 323 | { |
324 | struct timeval tv, *tvp; | ||
325 | int n; | ||
326 | extern Options options; | ||
327 | |||
324 | /* Add any selections by the channel mechanism. */ | 328 | /* Add any selections by the channel mechanism. */ |
325 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying); | 329 | channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, rekeying); |
326 | 330 | ||
@@ -349,7 +353,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
349 | /* clear mask since we did not call select() */ | 353 | /* clear mask since we did not call select() */ |
350 | memset(*readsetp, 0, *nallocp); | 354 | memset(*readsetp, 0, *nallocp); |
351 | memset(*writesetp, 0, *nallocp); | 355 | memset(*writesetp, 0, *nallocp); |
352 | return; | 356 | return 0; |
353 | } else { | 357 | } else { |
354 | FD_SET(connection_in, *readsetp); | 358 | FD_SET(connection_in, *readsetp); |
355 | } | 359 | } |
@@ -368,7 +372,21 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
368 | * SSH_MSG_IGNORE packet when the timeout expires. | 372 | * SSH_MSG_IGNORE packet when the timeout expires. |
369 | */ | 373 | */ |
370 | 374 | ||
371 | if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) { | 375 | /* |
376 | * We don't do the 'random' bit, but we want periodic ignored | ||
377 | * message anyway, so as to notice when the other ends TCP | ||
378 | * has given up during an outage. | ||
379 | */ | ||
380 | |||
381 | if (options.protocolkeepalives > 0) { | ||
382 | tvp = &tv; | ||
383 | tv.tv_sec = options.protocolkeepalives; | ||
384 | tv.tv_usec = 0; | ||
385 | } else | ||
386 | tvp = 0; | ||
387 | |||
388 | n = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); | ||
389 | if (n < 0) { | ||
372 | char buf[100]; | 390 | char buf[100]; |
373 | 391 | ||
374 | /* | 392 | /* |
@@ -380,12 +398,13 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
380 | memset(*writesetp, 0, *nallocp); | 398 | memset(*writesetp, 0, *nallocp); |
381 | 399 | ||
382 | if (errno == EINTR) | 400 | if (errno == EINTR) |
383 | return; | 401 | return 0; |
384 | /* Note: we might still have data in the buffers. */ | 402 | /* Note: we might still have data in the buffers. */ |
385 | snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); | 403 | snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); |
386 | buffer_append(&stderr_buffer, buf, strlen(buf)); | 404 | buffer_append(&stderr_buffer, buf, strlen(buf)); |
387 | quit_pending = 1; | 405 | quit_pending = 1; |
388 | } | 406 | } |
407 | return n == 0; | ||
389 | } | 408 | } |
390 | 409 | ||
391 | static void | 410 | static void |
@@ -846,6 +865,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
846 | { | 865 | { |
847 | fd_set *readset = NULL, *writeset = NULL; | 866 | fd_set *readset = NULL, *writeset = NULL; |
848 | double start_time, total_time; | 867 | double start_time, total_time; |
868 | int timed_out; | ||
849 | int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; | 869 | int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; |
850 | char buf[100]; | 870 | char buf[100]; |
851 | 871 | ||
@@ -959,7 +979,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
959 | * available on one of the descriptors). | 979 | * available on one of the descriptors). |
960 | */ | 980 | */ |
961 | max_fd2 = max_fd; | 981 | max_fd2 = max_fd; |
962 | client_wait_until_can_do_something(&readset, &writeset, | 982 | timed_out = client_wait_until_can_do_something(&readset, &writeset, |
963 | &max_fd2, &nalloc, rekeying); | 983 | &max_fd2, &nalloc, rekeying); |
964 | 984 | ||
965 | if (quit_pending) | 985 | if (quit_pending) |
@@ -983,6 +1003,21 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
983 | if (quit_pending) | 1003 | if (quit_pending) |
984 | break; | 1004 | break; |
985 | 1005 | ||
1006 | if(timed_out) { | ||
1007 | /* | ||
1008 | * Nothing is happening, so synthesize some | ||
1009 | * bogus activity | ||
1010 | */ | ||
1011 | packet_start(compat20 | ||
1012 | ? SSH2_MSG_IGNORE | ||
1013 | : SSH_MSG_IGNORE); | ||
1014 | packet_put_cstring(""); | ||
1015 | packet_send(); | ||
1016 | if (FD_ISSET(connection_out, writeset)) | ||
1017 | packet_write_poll(); | ||
1018 | continue; | ||
1019 | } | ||
1020 | |||
986 | if (!compat20) { | 1021 | if (!compat20) { |
987 | /* Buffer data from stdin */ | 1022 | /* Buffer data from stdin */ |
988 | client_process_input(readset); | 1023 | client_process_input(readset); |