diff options
Diffstat (limited to 'clientloop.c')
-rw-r--r-- | clientloop.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/clientloop.c b/clientloop.c index b45e7298a..37cecf5a6 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.195 2008/06/12 03:40:52 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.196 2008/06/12 04:06:00 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 |
@@ -174,6 +174,17 @@ struct channel_reply_ctx { | |||
174 | int id, do_close; | 174 | int id, do_close; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | /* Global request success/failure callbacks */ | ||
178 | struct global_confirm { | ||
179 | TAILQ_ENTRY(global_confirm) entry; | ||
180 | global_confirm_cb *cb; | ||
181 | void *ctx; | ||
182 | int ref_count; | ||
183 | }; | ||
184 | TAILQ_HEAD(global_confirms, global_confirm); | ||
185 | static struct global_confirms global_confirms = | ||
186 | TAILQ_HEAD_INITIALIZER(global_confirms); | ||
187 | |||
177 | /*XXX*/ | 188 | /*XXX*/ |
178 | extern Kex *xxx_kex; | 189 | extern Kex *xxx_kex; |
179 | 190 | ||
@@ -468,8 +479,19 @@ client_check_window_change(void) | |||
468 | static void | 479 | static void |
469 | client_global_request_reply(int type, u_int32_t seq, void *ctxt) | 480 | client_global_request_reply(int type, u_int32_t seq, void *ctxt) |
470 | { | 481 | { |
482 | struct global_confirm *gc; | ||
483 | |||
484 | if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) | ||
485 | return; | ||
486 | if (gc->cb != NULL) | ||
487 | gc->cb(type, seq, gc->ctx); | ||
488 | if (--gc->ref_count <= 0) { | ||
489 | TAILQ_REMOVE(&global_confirms, gc, entry); | ||
490 | bzero(gc, sizeof(*gc)); | ||
491 | xfree(gc); | ||
492 | } | ||
493 | |||
471 | keep_alive_timeouts = 0; | 494 | keep_alive_timeouts = 0; |
472 | client_global_request_reply_fwd(type, seq, ctxt); | ||
473 | } | 495 | } |
474 | 496 | ||
475 | static void | 497 | static void |
@@ -483,6 +505,8 @@ server_alive_check(void) | |||
483 | packet_put_cstring("keepalive@openssh.com"); | 505 | packet_put_cstring("keepalive@openssh.com"); |
484 | packet_put_char(1); /* boolean: want reply */ | 506 | packet_put_char(1); /* boolean: want reply */ |
485 | packet_send(); | 507 | packet_send(); |
508 | /* Insert an empty placeholder to maintain ordering */ | ||
509 | client_register_global_confirm(NULL, NULL); | ||
486 | } | 510 | } |
487 | 511 | ||
488 | /* | 512 | /* |
@@ -702,6 +726,27 @@ client_expect_confirm(int id, const char *request, int do_close) | |||
702 | client_abandon_status_confirm, cr); | 726 | client_abandon_status_confirm, cr); |
703 | } | 727 | } |
704 | 728 | ||
729 | void | ||
730 | client_register_global_confirm(global_confirm_cb *cb, void *ctx) | ||
731 | { | ||
732 | struct global_confirm *gc, *first_gc; | ||
733 | |||
734 | /* Coalesce identical callbacks */ | ||
735 | first_gc = TAILQ_FIRST(&global_confirms); | ||
736 | if (first_gc && first_gc->cb == cb && first_gc->ctx == ctx) { | ||
737 | if (++first_gc->ref_count >= INT_MAX) | ||
738 | fatal("%s: first_gc->ref_count = %d", | ||
739 | __func__, first_gc->ref_count); | ||
740 | return; | ||
741 | } | ||
742 | |||
743 | gc = xmalloc(sizeof(*gc)); | ||
744 | gc->cb = cb; | ||
745 | gc->ctx = ctx; | ||
746 | gc->ref_count = 1; | ||
747 | TAILQ_INSERT_TAIL(&global_confirms, gc, entry); | ||
748 | } | ||
749 | |||
705 | static void | 750 | static void |
706 | process_cmdline(void) | 751 | process_cmdline(void) |
707 | { | 752 | { |