Mercurial > dropbear
comparison common-channel.c @ 1625:79eef94ccea9
Split ChanType closehandler() and cleanup() so that dbclient doesn't
lose exit status messages
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 14 Nov 2018 22:57:56 +0800 |
parents | 5916af64acd4 |
children | c584b5602bd8 |
comparison
equal
deleted
inserted
replaced
1624:1f3fb83b0524 | 1625:79eef94ccea9 |
---|---|
142 newchan = (struct Channel*)m_malloc(sizeof(struct Channel)); | 142 newchan = (struct Channel*)m_malloc(sizeof(struct Channel)); |
143 newchan->type = type; | 143 newchan->type = type; |
144 newchan->index = i; | 144 newchan->index = i; |
145 newchan->sent_close = newchan->recv_close = 0; | 145 newchan->sent_close = newchan->recv_close = 0; |
146 newchan->sent_eof = newchan->recv_eof = 0; | 146 newchan->sent_eof = newchan->recv_eof = 0; |
147 newchan->close_handler_done = 0; | |
148 | 147 |
149 newchan->remotechan = remotechan; | 148 newchan->remotechan = remotechan; |
150 newchan->transwindow = transwindow; | 149 newchan->transwindow = transwindow; |
151 newchan->transmaxpacket = transmaxpacket; | 150 newchan->transmaxpacket = transmaxpacket; |
152 | 151 |
284 TRACE2(("writebuf size %d extrabuf size %d", | 283 TRACE2(("writebuf size %d extrabuf size %d", |
285 channel->writebuf ? cbuf_getused(channel->writebuf) : 0, | 284 channel->writebuf ? cbuf_getused(channel->writebuf) : 0, |
286 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) | 285 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0)) |
287 | 286 |
288 if (!channel->flushing | 287 if (!channel->flushing |
289 && !channel->close_handler_done | 288 && !channel->sent_close |
290 && channel->type->check_close | 289 && channel->type->check_close |
291 && channel->type->check_close(channel)) | 290 && channel->type->check_close(channel)) |
292 { | 291 { |
293 channel->flushing = 1; | 292 channel->flushing = 1; |
294 } | 293 } |
296 /* if a type-specific check_close is defined we will only exit | 295 /* if a type-specific check_close is defined we will only exit |
297 once that has been triggered. this is only used for a server "session" | 296 once that has been triggered. this is only used for a server "session" |
298 channel, to ensure that the shell has exited (and the exit status | 297 channel, to ensure that the shell has exited (and the exit status |
299 retrieved) before we close things up. */ | 298 retrieved) before we close things up. */ |
300 if (!channel->type->check_close | 299 if (!channel->type->check_close |
301 || channel->close_handler_done | 300 || channel->sent_close |
302 || channel->type->check_close(channel)) { | 301 || channel->type->check_close(channel)) { |
303 close_allowed = 1; | 302 close_allowed = 1; |
304 } | 303 } |
305 | 304 |
306 if (channel->recv_close && !write_pending(channel) && close_allowed) { | 305 if (channel->recv_close && !write_pending(channel) && close_allowed) { |
383 | 382 |
384 /* Send the close message and set the channel as closed */ | 383 /* Send the close message and set the channel as closed */ |
385 static void send_msg_channel_close(struct Channel *channel) { | 384 static void send_msg_channel_close(struct Channel *channel) { |
386 | 385 |
387 TRACE(("enter send_msg_channel_close %p", (void*)channel)) | 386 TRACE(("enter send_msg_channel_close %p", (void*)channel)) |
388 if (channel->type->closehandler | 387 if (channel->type->closehandler) { |
389 && !channel->close_handler_done) { | |
390 channel->type->closehandler(channel); | 388 channel->type->closehandler(channel); |
391 channel->close_handler_done = 1; | |
392 } | 389 } |
393 | 390 |
394 CHECKCLEARTOWRITE(); | 391 CHECKCLEARTOWRITE(); |
395 | 392 |
396 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE); | 393 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE); |
659 m_close(channel->readfd); | 656 m_close(channel->readfd); |
660 TRACE(("CLOSE errfd %d", channel->errfd)) | 657 TRACE(("CLOSE errfd %d", channel->errfd)) |
661 m_close(channel->errfd); | 658 m_close(channel->errfd); |
662 } | 659 } |
663 | 660 |
664 if (!channel->close_handler_done | 661 if (channel->type->cleanup) { |
665 && channel->type->closehandler) { | 662 channel->type->cleanup(channel); |
666 channel->type->closehandler(channel); | |
667 channel->close_handler_done = 1; | |
668 } | 663 } |
669 | 664 |
670 if (channel->conn_pending) { | 665 if (channel->conn_pending) { |
671 cancel_connect(channel->conn_pending); | 666 cancel_connect(channel->conn_pending); |
672 } | 667 } |
688 | 683 |
689 channel = getchannel(); | 684 channel = getchannel(); |
690 | 685 |
691 TRACE(("enter recv_msg_channel_request %p", (void*)channel)) | 686 TRACE(("enter recv_msg_channel_request %p", (void*)channel)) |
692 | 687 |
693 if (channel->sent_close) { | 688 if (channel->type->reqhandler) { |
694 TRACE(("leave recv_msg_channel_request: already closed channel")) | |
695 return; | |
696 } | |
697 | |
698 if (channel->type->reqhandler | |
699 && !channel->close_handler_done) { | |
700 channel->type->reqhandler(channel); | 689 channel->type->reqhandler(channel); |
701 } else { | 690 } else { |
702 int wantreply; | 691 int wantreply; |
703 buf_eatstring(ses.payload); | 692 buf_eatstring(ses.payload); |
704 wantreply = buf_getbool(ses.payload); | 693 wantreply = buf_getbool(ses.payload); |
1009 | 998 |
1010 /* Send a failure message */ | 999 /* Send a failure message */ |
1011 void send_msg_channel_failure(const struct Channel *channel) { | 1000 void send_msg_channel_failure(const struct Channel *channel) { |
1012 | 1001 |
1013 TRACE(("enter send_msg_channel_failure")) | 1002 TRACE(("enter send_msg_channel_failure")) |
1003 | |
1004 if (channel->sent_close) { | |
1005 TRACE(("Skipping sending msg_channel_failure for closed channel")) | |
1006 return; | |
1007 } | |
1014 CHECKCLEARTOWRITE(); | 1008 CHECKCLEARTOWRITE(); |
1015 | 1009 |
1016 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE); | 1010 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE); |
1017 buf_putint(ses.writepayload, channel->remotechan); | 1011 buf_putint(ses.writepayload, channel->remotechan); |
1018 | 1012 |
1022 | 1016 |
1023 /* Send a success message */ | 1017 /* Send a success message */ |
1024 void send_msg_channel_success(const struct Channel *channel) { | 1018 void send_msg_channel_success(const struct Channel *channel) { |
1025 | 1019 |
1026 TRACE(("enter send_msg_channel_success")) | 1020 TRACE(("enter send_msg_channel_success")) |
1021 if (channel->sent_close) { | |
1022 TRACE(("Skipping sending msg_channel_success for closed channel")) | |
1023 return; | |
1024 } | |
1027 CHECKCLEARTOWRITE(); | 1025 CHECKCLEARTOWRITE(); |
1028 | 1026 |
1029 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS); | 1027 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS); |
1030 buf_putint(ses.writepayload, channel->remotechan); | 1028 buf_putint(ses.writepayload, channel->remotechan); |
1031 | 1029 |