Mercurial > dropbear
comparison common-channel.c @ 70:b0316ce64e4b
Merging in the changes from 0.41-0.43 main Dropbear tree
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 12 Aug 2004 16:41:58 +0000 |
parents | 20563735e8b5 |
children | d3eb1fa8484e |
comparison
equal
deleted
inserted
replaced
69:59d16db56e9f | 70:b0316ce64e4b |
---|---|
170 /* Iterate through the channels, performing IO if available */ | 170 /* Iterate through the channels, performing IO if available */ |
171 void channelio(fd_set *readfd, fd_set *writefd) { | 171 void channelio(fd_set *readfd, fd_set *writefd) { |
172 | 172 |
173 struct Channel *channel; | 173 struct Channel *channel; |
174 unsigned int i; | 174 unsigned int i; |
175 int ret; | |
175 | 176 |
176 /* iterate through all the possible channels */ | 177 /* iterate through all the possible channels */ |
177 for (i = 0; i < ses.chansize; i++) { | 178 for (i = 0; i < ses.chansize; i++) { |
178 | 179 |
179 channel = ses.channels[i]; | 180 channel = ses.channels[i]; |
194 | 195 |
195 /* if we can read from the infd, it might be closed, so we try to | 196 /* if we can read from the infd, it might be closed, so we try to |
196 * see if it has errors */ | 197 * see if it has errors */ |
197 if (channel->infd >= 0 && channel->infd != channel->outfd | 198 if (channel->infd >= 0 && channel->infd != channel->outfd |
198 && FD_ISSET(channel->infd, readfd)) { | 199 && FD_ISSET(channel->infd, readfd)) { |
199 int ret; | 200 if (channel->initconn) { |
200 ret = write(channel->infd, NULL, 0); | 201 /* Handling for "in progress" connection - this is needed |
202 * to avoid spinning 100% CPU when we connect to a server | |
203 * which doesn't send anything (tcpfwding) */ | |
204 checkinitdone(channel); | |
205 continue; /* Important not to use the channel after | |
206 checkinitdone(), as it may be NULL */ | |
207 } | |
208 ret = write(channel->infd, NULL, 0); /* Fake write */ | |
201 if (ret < 0 && errno != EINTR && errno != EAGAIN) { | 209 if (ret < 0 && errno != EINTR && errno != EAGAIN) { |
202 closeinfd(channel); | 210 closeinfd(channel); |
203 } | 211 } |
204 } | 212 } |
205 | 213 |
207 if (channel->infd >= 0 && FD_ISSET(channel->infd, writefd)) { | 215 if (channel->infd >= 0 && FD_ISSET(channel->infd, writefd)) { |
208 if (channel->initconn) { | 216 if (channel->initconn) { |
209 checkinitdone(channel); | 217 checkinitdone(channel); |
210 continue; /* Important not to use the channel after | 218 continue; /* Important not to use the channel after |
211 checkinitdone(), as it may be NULL */ | 219 checkinitdone(), as it may be NULL */ |
212 } else { | |
213 writechannel(channel); | |
214 } | 220 } |
221 writechannel(channel); | |
215 } | 222 } |
216 | 223 |
217 /* now handle any of the channel-closing type stuff */ | 224 /* now handle any of the channel-closing type stuff */ |
218 checkclose(channel); | 225 checkclose(channel); |
219 | 226 |
283 | 290 |
284 TRACE(("enter checkinitdone")); | 291 TRACE(("enter checkinitdone")); |
285 | 292 |
286 if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen) | 293 if (getsockopt(channel->infd, SOL_SOCKET, SO_ERROR, &val, &vallen) |
287 || val != 0) { | 294 || val != 0) { |
295 send_msg_channel_open_failure(channel->remotechan, | |
296 SSH_OPEN_CONNECT_FAILED, "", ""); | |
288 close(channel->infd); | 297 close(channel->infd); |
289 deletechannel(channel); | 298 deletechannel(channel); |
290 TRACE(("leave checkinitdone: fail")); | 299 TRACE(("leave checkinitdone: fail")); |
291 } else { | 300 } else { |
301 send_msg_channel_open_confirmation(channel, channel->recvwindow, | |
302 channel->recvmaxpacket); | |
292 channel->outfd = channel->infd; | 303 channel->outfd = channel->infd; |
293 channel->initconn = 0; | 304 channel->initconn = 0; |
294 TRACE(("leave checkinitdone: success")); | 305 TRACE(("leave checkinitdone: success")); |
295 } | 306 } |
296 } | 307 } |
487 | 498 |
488 TRACE(("enter removechannel")); | 499 TRACE(("enter removechannel")); |
489 TRACE(("channel index is %d", channel->index)); | 500 TRACE(("channel index is %d", channel->index)); |
490 | 501 |
491 buf_free(channel->writebuf); | 502 buf_free(channel->writebuf); |
503 channel->writebuf = NULL; | |
492 | 504 |
493 /* close the FDs in case they haven't been done | 505 /* close the FDs in case they haven't been done |
494 * yet (ie they were shutdown etc */ | 506 * yet (ie they were shutdown etc */ |
495 close(channel->infd); | 507 close(channel->infd); |
496 close(channel->outfd); | 508 close(channel->outfd); |
497 if (channel->errfd >= 0) { | 509 if (channel->errfd >= 0) { |
498 close(channel->errfd); | 510 close(channel->errfd); |
499 } | 511 } |
512 channel->typedata = NULL; | |
500 | 513 |
501 deletechannel(channel); | 514 deletechannel(channel); |
502 | 515 |
503 TRACE(("leave removechannel")); | 516 TRACE(("leave removechannel")); |
504 } | 517 } |
585 if (len == 0 || errno != EINTR) { | 598 if (len == 0 || errno != EINTR) { |
586 closeoutfd(channel, fd); | 599 closeoutfd(channel, fd); |
587 TRACE(("leave send_msg_channel_data: read err %d", channel->index)); | 600 TRACE(("leave send_msg_channel_data: read err %d", channel->index)); |
588 } | 601 } |
589 buf_free(buf); | 602 buf_free(buf); |
603 buf = NULL; | |
590 return; | 604 return; |
591 } | 605 } |
592 buf_incrlen(buf, len); | 606 buf_incrlen(buf, len); |
593 | 607 |
594 buf_putbyte(ses.writepayload, | 608 buf_putbyte(ses.writepayload, |
599 buf_putint(ses.writepayload, exttype); | 613 buf_putint(ses.writepayload, exttype); |
600 } | 614 } |
601 | 615 |
602 buf_putstring(ses.writepayload, buf_getptr(buf, len), len); | 616 buf_putstring(ses.writepayload, buf_getptr(buf, len), len); |
603 buf_free(buf); | 617 buf_free(buf); |
618 buf = NULL; | |
604 | 619 |
605 channel->transwindow -= len; | 620 channel->transwindow -= len; |
606 | 621 |
607 encrypt_packet(); | 622 encrypt_packet(); |
608 TRACE(("leave send_msg_channel_data")); | 623 TRACE(("leave send_msg_channel_data")); |
762 } | 777 } |
763 | 778 |
764 if (channel->type->inithandler) { | 779 if (channel->type->inithandler) { |
765 ret = channel->type->inithandler(channel); | 780 ret = channel->type->inithandler(channel); |
766 if (ret > 0) { | 781 if (ret > 0) { |
782 if (ret == SSH_OPEN_IN_PROGRESS) { | |
783 /* We'll send the confirmation later */ | |
784 goto cleanup; | |
785 } | |
767 errtype = ret; | 786 errtype = ret; |
768 deletechannel(channel); | 787 deletechannel(channel); |
769 TRACE(("inithandler returned failure %d", ret)); | 788 TRACE(("inithandler returned failure %d", ret)); |
770 goto failure; | 789 goto failure; |
771 } | 790 } |