comparison common-channel.c @ 1025:02baa0b334e8 fastopen

async connections working
author Matt Johnston <matt@ucc.asn.au>
date Wed, 18 Feb 2015 22:46:15 +0800
parents 0bb16232e7c4
children 0da8ba489c23
comparison
equal deleted inserted replaced
1024:aac0095dc3b4 1025:02baa0b334e8
46 unsigned int incr); 46 unsigned int incr);
47 static void send_msg_channel_data(struct Channel *channel, int isextended); 47 static void send_msg_channel_data(struct Channel *channel, int isextended);
48 static void send_msg_channel_eof(struct Channel *channel); 48 static void send_msg_channel_eof(struct Channel *channel);
49 static void send_msg_channel_close(struct Channel *channel); 49 static void send_msg_channel_close(struct Channel *channel);
50 static void remove_channel(struct Channel *channel); 50 static void remove_channel(struct Channel *channel);
51 static void check_in_progress(struct Channel *channel);
52 static unsigned int write_pending(struct Channel * channel); 51 static unsigned int write_pending(struct Channel * channel);
53 static void check_close(struct Channel *channel); 52 static void check_close(struct Channel *channel);
54 static void close_chan_fd(struct Channel *channel, int fd, int how); 53 static void close_chan_fd(struct Channel *channel, int fd, int how);
55 54
56 #define FD_UNINIT (-2) 55 #define FD_UNINIT (-2)
161 160
162 newchan->typedata = NULL; 161 newchan->typedata = NULL;
163 newchan->writefd = FD_UNINIT; 162 newchan->writefd = FD_UNINIT;
164 newchan->readfd = FD_UNINIT; 163 newchan->readfd = FD_UNINIT;
165 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */ 164 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
166 newchan->initconn = 0;
167 newchan->await_open = 0; 165 newchan->await_open = 0;
168 newchan->flushing = 0; 166 newchan->flushing = 0;
169 167
170 newchan->writebuf = cbuf_new(0); /* resized later by chan_initwritebuf */ 168 newchan->writebuf = cbuf_new(0); /* resized later by chan_initwritebuf */
171 newchan->recvwindow = 0; 169 newchan->recvwindow = 0;
240 do_check_close = 1; 238 do_check_close = 1;
241 } 239 }
242 240
243 /* write to program/pipe stdin */ 241 /* write to program/pipe stdin */
244 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) { 242 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
245 if (channel->initconn) {
246 /* XXX should this go somewhere cleaner? */
247 check_in_progress(channel);
248 continue; /* Important not to use the channel after
249 check_in_progress(), as it may be NULL */
250 }
251 writechannel(channel, channel->writefd, channel->writebuf); 243 writechannel(channel, channel->writefd, channel->writebuf);
252 do_check_close = 1; 244 do_check_close = 1;
253 } 245 }
254 246
255 /* stderr for client mode */ 247 /* stderr for client mode */
372 364
373 /* Check whether a deferred (EINPROGRESS) connect() was successful, and 365 /* Check whether a deferred (EINPROGRESS) connect() was successful, and
374 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so 366 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
375 * it is important that the channel reference isn't used after a call to this 367 * it is important that the channel reference isn't used after a call to this
376 * function */ 368 * function */
377 static void check_in_progress(struct Channel *channel) { 369 void channel_connect_done(int result, int sock, void* user_data, const char* UNUSED(errstring)) {
378 370
379 int val; 371 struct Channel *channel = user_data;
380 socklen_t vallen = sizeof(val); 372
381 373 TRACE(("enter channel_connect_done"))
382 TRACE(("enter check_in_progress")) 374
383 375 if (result == DROPBEAR_SUCCESS)
384 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen) 376 {
385 || val != 0) { 377 channel->readfd = channel->writefd = sock;
386 send_msg_channel_open_failure(channel->remotechan, 378 channel->conn_pending = NULL;
387 SSH_OPEN_CONNECT_FAILED, "", "");
388 close(channel->writefd);
389 remove_channel(channel);
390 TRACE(("leave check_in_progress: fail"))
391 } else {
392 chan_initwritebuf(channel); 379 chan_initwritebuf(channel);
393 send_msg_channel_open_confirmation(channel, channel->recvwindow, 380 send_msg_channel_open_confirmation(channel, channel->recvwindow,
394 channel->recvmaxpacket); 381 channel->recvmaxpacket);
395 channel->readfd = channel->writefd; 382 TRACE(("leave channel_connect_done: success"))
396 channel->initconn = 0; 383 }
397 TRACE(("leave check_in_progress: success")) 384 else
385 {
386 send_msg_channel_open_failure(channel->remotechan,
387 SSH_OPEN_CONNECT_FAILED, "", "");
388 remove_channel(channel);
389 TRACE(("leave check_in_progress: fail"))
398 } 390 }
399 } 391 }
400 392
401 393
402 /* Send the close message and set the channel as closed */ 394 /* Send the close message and set the channel as closed */
512 FD_SET(channel->errfd, readfds); 504 FD_SET(channel->errfd, readfds);
513 } 505 }
514 } 506 }
515 507
516 /* Stuff from the wire */ 508 /* Stuff from the wire */
517 if (channel->initconn 509 if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
518 ||(channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0)) {
519 FD_SET(channel->writefd, writefds); 510 FD_SET(channel->writefd, writefds);
520 } 511 }
521 512
522 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0 513 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
523 && cbuf_getused(channel->extrabuf) > 0) { 514 && cbuf_getused(channel->extrabuf) > 0) {
597 && channel->type->closehandler) { 588 && channel->type->closehandler) {
598 channel->type->closehandler(channel); 589 channel->type->closehandler(channel);
599 channel->close_handler_done = 1; 590 channel->close_handler_done = 1;
600 } 591 }
601 592
593 if (channel->conn_pending) {
594 cancel_connect(channel->conn_pending);
595 }
596
602 ses.channels[channel->index] = NULL; 597 ses.channels[channel->index] = NULL;
603 m_free(channel); 598 m_free(channel);
604 ses.chancount--; 599 ses.chancount--;
605 600
606 update_channel_prio(); 601 update_channel_prio();
1147 size_t i; 1142 size_t i;
1148 for (i = 0; i < ses.chansize; i++) { 1143 for (i = 0; i < ses.chansize; i++) {
1149 struct Channel *chan = ses.channels[i]; 1144 struct Channel *chan = ses.channels[i];
1150 if (chan 1145 if (chan
1151 && !(chan->sent_eof || chan->recv_eof) 1146 && !(chan->sent_eof || chan->recv_eof)
1152 && !(chan->await_open || chan->initconn)) { 1147 && !(chan->await_open)) {
1153 return chan; 1148 return chan;
1154 } 1149 }
1155 } 1150 }
1156 return NULL; 1151 return NULL;
1157 } 1152 }