diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/channels.c b/channels.c index 71a345109..f10427c17 100644 --- a/channels.c +++ b/channels.c | |||
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: channels.c,v 1.92 2001/02/16 13:38:18 markus Exp $"); | 43 | RCSID("$OpenBSD: channels.c,v 1.93 2001/02/28 08:54:55 markus Exp $"); |
44 | 44 | ||
45 | #include <openssl/rsa.h> | 45 | #include <openssl/rsa.h> |
46 | #include <openssl/dsa.h> | 46 | #include <openssl/dsa.h> |
@@ -824,7 +824,14 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) | |||
824 | buffer_len(&c->extended)); | 824 | buffer_len(&c->extended)); |
825 | debug2("channel %d: written %d to efd %d", | 825 | debug2("channel %d: written %d to efd %d", |
826 | c->self, len, c->efd); | 826 | c->self, len, c->efd); |
827 | if (len > 0) { | 827 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
828 | return 1; | ||
829 | if (len <= 0) { | ||
830 | debug2("channel %d: closing write-efd %d", | ||
831 | c->self, c->efd); | ||
832 | close(c->efd); | ||
833 | c->efd = -1; | ||
834 | } else { | ||
828 | buffer_consume(&c->extended, len); | 835 | buffer_consume(&c->extended, len); |
829 | c->local_consumed += len; | 836 | c->local_consumed += len; |
830 | } | 837 | } |
@@ -833,19 +840,22 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) | |||
833 | len = read(c->efd, buf, sizeof(buf)); | 840 | len = read(c->efd, buf, sizeof(buf)); |
834 | debug2("channel %d: read %d from efd %d", | 841 | debug2("channel %d: read %d from efd %d", |
835 | c->self, len, c->efd); | 842 | c->self, len, c->efd); |
836 | if (len == 0) { | 843 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
837 | debug("channel %d: closing efd %d", | 844 | return 1; |
845 | if (len <= 0) { | ||
846 | debug2("channel %d: closing read-efd %d", | ||
838 | c->self, c->efd); | 847 | c->self, c->efd); |
839 | close(c->efd); | 848 | close(c->efd); |
840 | c->efd = -1; | 849 | c->efd = -1; |
841 | } else if (len > 0) | 850 | } else { |
842 | buffer_append(&c->extended, buf, len); | 851 | buffer_append(&c->extended, buf, len); |
852 | } | ||
843 | } | 853 | } |
844 | } | 854 | } |
845 | return 1; | 855 | return 1; |
846 | } | 856 | } |
847 | int | 857 | int |
848 | channel_check_window(Channel *c, fd_set * readset, fd_set * writeset) | 858 | channel_check_window(Channel *c) |
849 | { | 859 | { |
850 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && | 860 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && |
851 | c->local_window < c->local_window_max/2 && | 861 | c->local_window < c->local_window_max/2 && |
@@ -876,7 +886,8 @@ channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset) | |||
876 | channel_handle_rfd(c, readset, writeset); | 886 | channel_handle_rfd(c, readset, writeset); |
877 | channel_handle_wfd(c, readset, writeset); | 887 | channel_handle_wfd(c, readset, writeset); |
878 | channel_handle_efd(c, readset, writeset); | 888 | channel_handle_efd(c, readset, writeset); |
879 | channel_check_window(c, readset, writeset); | 889 | |
890 | channel_check_window(c); | ||
880 | } | 891 | } |
881 | 892 | ||
882 | void | 893 | void |
@@ -984,7 +995,24 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) | |||
984 | if (ftab[c->type] == NULL) | 995 | if (ftab[c->type] == NULL) |
985 | continue; | 996 | continue; |
986 | (*ftab[c->type])(c, readset, writeset); | 997 | (*ftab[c->type])(c, readset, writeset); |
987 | chan_delete_if_full_closed(c); | 998 | if (chan_is_dead(c)) { |
999 | /* | ||
1000 | * we have to remove the fd's from the select mask | ||
1001 | * before the channels are free'd and the fd's are | ||
1002 | * closed | ||
1003 | */ | ||
1004 | if (c->wfd != -1) | ||
1005 | FD_CLR(c->wfd, writeset); | ||
1006 | if (c->rfd != -1) | ||
1007 | FD_CLR(c->rfd, readset); | ||
1008 | if (c->efd != -1) { | ||
1009 | if (c->extended_usage == CHAN_EXTENDED_READ) | ||
1010 | FD_CLR(c->efd, readset); | ||
1011 | if (c->extended_usage == CHAN_EXTENDED_WRITE) | ||
1012 | FD_CLR(c->efd, writeset); | ||
1013 | } | ||
1014 | channel_free(c->self); | ||
1015 | } | ||
988 | } | 1016 | } |
989 | } | 1017 | } |
990 | 1018 | ||
@@ -1037,19 +1065,18 @@ channel_output_poll() | |||
1037 | } else { | 1065 | } else { |
1038 | if (c->type != SSH_CHANNEL_OPEN) | 1066 | if (c->type != SSH_CHANNEL_OPEN) |
1039 | continue; | 1067 | continue; |
1040 | if (c->istate != CHAN_INPUT_OPEN && | ||
1041 | c->istate != CHAN_INPUT_WAIT_DRAIN) | ||
1042 | continue; | ||
1043 | } | 1068 | } |
1044 | if (compat20 && | 1069 | if (compat20 && |
1045 | (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { | 1070 | (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { |
1071 | /* XXX is this true? */ | ||
1046 | debug("channel: %d: no data after CLOSE", c->self); | 1072 | debug("channel: %d: no data after CLOSE", c->self); |
1047 | continue; | 1073 | continue; |
1048 | } | 1074 | } |
1049 | 1075 | ||
1050 | /* Get the amount of buffered data for this channel. */ | 1076 | /* Get the amount of buffered data for this channel. */ |
1051 | len = buffer_len(&c->input); | 1077 | if ((c->istate == CHAN_INPUT_OPEN || |
1052 | if (len > 0) { | 1078 | c->istate == CHAN_INPUT_WAIT_DRAIN) && |
1079 | (len = buffer_len(&c->input)) > 0) { | ||
1053 | /* Send some data for the other side over the secure connection. */ | 1080 | /* Send some data for the other side over the secure connection. */ |
1054 | if (compat20) { | 1081 | if (compat20) { |
1055 | if (len > c->remote_window) | 1082 | if (len > c->remote_window) |
@@ -1089,6 +1116,9 @@ channel_output_poll() | |||
1089 | c->remote_window > 0 && | 1116 | c->remote_window > 0 && |
1090 | (len = buffer_len(&c->extended)) > 0 && | 1117 | (len = buffer_len(&c->extended)) > 0 && |
1091 | c->extended_usage == CHAN_EXTENDED_READ) { | 1118 | c->extended_usage == CHAN_EXTENDED_READ) { |
1119 | debug2("channel %d: rwin %d elen %d euse %d", | ||
1120 | c->self, c->remote_window, buffer_len(&c->extended), | ||
1121 | c->extended_usage); | ||
1092 | if (len > c->remote_window) | 1122 | if (len > c->remote_window) |
1093 | len = c->remote_window; | 1123 | len = c->remote_window; |
1094 | if (len > c->remote_maxpacket) | 1124 | if (len > c->remote_maxpacket) |
@@ -1100,6 +1130,7 @@ channel_output_poll() | |||
1100 | packet_send(); | 1130 | packet_send(); |
1101 | buffer_consume(&c->extended, len); | 1131 | buffer_consume(&c->extended, len); |
1102 | c->remote_window -= len; | 1132 | c->remote_window -= len; |
1133 | debug2("channel %d: sent ext data %d", c->self, len); | ||
1103 | } | 1134 | } |
1104 | } | 1135 | } |
1105 | } | 1136 | } |