Mercurial > dropbear
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 } |