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 cd2eab77a..6d19b4a25 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 |
@@ -844,6 +863,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
844 | { | 863 | { |
845 | fd_set *readset = NULL, *writeset = NULL; | 864 | fd_set *readset = NULL, *writeset = NULL; |
846 | double start_time, total_time; | 865 | double start_time, total_time; |
866 | int timed_out; | ||
847 | int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; | 867 | int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0; |
848 | char buf[100]; | 868 | char buf[100]; |
849 | 869 | ||
@@ -951,7 +971,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
951 | * available on one of the descriptors). | 971 | * available on one of the descriptors). |
952 | */ | 972 | */ |
953 | max_fd2 = max_fd; | 973 | max_fd2 = max_fd; |
954 | client_wait_until_can_do_something(&readset, &writeset, | 974 | timed_out = client_wait_until_can_do_something(&readset, &writeset, |
955 | &max_fd2, &nalloc, rekeying); | 975 | &max_fd2, &nalloc, rekeying); |
956 | 976 | ||
957 | if (quit_pending) | 977 | if (quit_pending) |
@@ -975,6 +995,21 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
975 | if (quit_pending) | 995 | if (quit_pending) |
976 | break; | 996 | break; |
977 | 997 | ||
998 | if(timed_out) { | ||
999 | /* | ||
1000 | * Nothing is happening, so synthesize some | ||
1001 | * bogus activity | ||
1002 | */ | ||
1003 | packet_start(compat20 | ||
1004 | ? SSH2_MSG_IGNORE | ||
1005 | : SSH_MSG_IGNORE); | ||
1006 | packet_put_cstring(""); | ||
1007 | packet_send(); | ||
1008 | if (FD_ISSET(connection_out, writeset)) | ||
1009 | packet_write_poll(); | ||
1010 | continue; | ||
1011 | } | ||
1012 | |||
978 | if (!compat20) { | 1013 | if (!compat20) { |
979 | /* Buffer data from stdin */ | 1014 | /* Buffer data from stdin */ |
980 | client_process_input(readset); | 1015 | client_process_input(readset); |