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 }