diff options
author | Damien Miller <djm@mindrot.org> | 2010-05-21 14:57:10 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2010-05-21 14:57:10 +1000 |
commit | d530f5f471491b6be9edb58a063f2590e4dce48d (patch) | |
tree | e536e2b4031a4dd70026ff49c39b02b72af06f30 /channels.c | |
parent | c6afb5f2c095a6a4380cc13a6480abb7614d949f (diff) |
- djm@cvs.openbsd.org 2010/05/14 23:29:23
[channels.c channels.h mux.c ssh.c]
Pause the mux channel while waiting for reply from aynch callbacks.
Prevents misordering of replies if new requests arrive while waiting.
Extend channel open confirm callback to allow signalling failure
conditions as well as success. Use this to 1) fix a memory leak, 2)
start using the above pause mechanism and 3) delay sending a success/
failure message on mux slave session open until we receive a reply from
the server.
motivated by and with feedback from markus@
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/channels.c b/channels.c index a55d27817..0f750c4d4 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.303 2010/01/30 21:12:08 djm Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.304 2010/05/14 23:29:23 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -330,6 +330,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
330 | c->ctl_chan = -1; | 330 | c->ctl_chan = -1; |
331 | c->mux_rcb = NULL; | 331 | c->mux_rcb = NULL; |
332 | c->mux_ctx = NULL; | 332 | c->mux_ctx = NULL; |
333 | c->mux_pause = 0; | ||
333 | c->delayed = 1; /* prevent call to channel_post handler */ | 334 | c->delayed = 1; /* prevent call to channel_post handler */ |
334 | TAILQ_INIT(&c->status_confirms); | 335 | TAILQ_INIT(&c->status_confirms); |
335 | debug("channel %d: new [%s]", found, remote_name); | 336 | debug("channel %d: new [%s]", found, remote_name); |
@@ -703,7 +704,7 @@ channel_register_status_confirm(int id, channel_confirm_cb *cb, | |||
703 | } | 704 | } |
704 | 705 | ||
705 | void | 706 | void |
706 | channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx) | 707 | channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx) |
707 | { | 708 | { |
708 | Channel *c = channel_lookup(id); | 709 | Channel *c = channel_lookup(id); |
709 | 710 | ||
@@ -991,7 +992,7 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) | |||
991 | static void | 992 | static void |
992 | channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset) | 993 | channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset) |
993 | { | 994 | { |
994 | if (c->istate == CHAN_INPUT_OPEN && | 995 | if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && |
995 | buffer_check_alloc(&c->input, CHAN_RBUF)) | 996 | buffer_check_alloc(&c->input, CHAN_RBUF)) |
996 | FD_SET(c->rfd, readset); | 997 | FD_SET(c->rfd, readset); |
997 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) { | 998 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) { |
@@ -1840,7 +1841,7 @@ channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset) | |||
1840 | if (!compat20) | 1841 | if (!compat20) |
1841 | fatal("%s: entered with !compat20", __func__); | 1842 | fatal("%s: entered with !compat20", __func__); |
1842 | 1843 | ||
1843 | if (c->rfd != -1 && FD_ISSET(c->rfd, readset) && | 1844 | if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) && |
1844 | (c->istate == CHAN_INPUT_OPEN || | 1845 | (c->istate == CHAN_INPUT_OPEN || |
1845 | c->istate == CHAN_INPUT_WAIT_DRAIN)) { | 1846 | c->istate == CHAN_INPUT_WAIT_DRAIN)) { |
1846 | /* | 1847 | /* |
@@ -2463,7 +2464,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) | |||
2463 | c->remote_maxpacket = packet_get_int(); | 2464 | c->remote_maxpacket = packet_get_int(); |
2464 | if (c->open_confirm) { | 2465 | if (c->open_confirm) { |
2465 | debug2("callback start"); | 2466 | debug2("callback start"); |
2466 | c->open_confirm(c->self, c->open_confirm_ctx); | 2467 | c->open_confirm(c->self, 1, c->open_confirm_ctx); |
2467 | debug2("callback done"); | 2468 | debug2("callback done"); |
2468 | } | 2469 | } |
2469 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, | 2470 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, |
@@ -2514,6 +2515,11 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) | |||
2514 | xfree(msg); | 2515 | xfree(msg); |
2515 | if (lang != NULL) | 2516 | if (lang != NULL) |
2516 | xfree(lang); | 2517 | xfree(lang); |
2518 | if (c->open_confirm) { | ||
2519 | debug2("callback start"); | ||
2520 | c->open_confirm(c->self, 0, c->open_confirm_ctx); | ||
2521 | debug2("callback done"); | ||
2522 | } | ||
2517 | } | 2523 | } |
2518 | packet_check_eom(); | 2524 | packet_check_eom(); |
2519 | /* Schedule the channel for cleanup/deletion. */ | 2525 | /* Schedule the channel for cleanup/deletion. */ |