summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c49
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 */
178struct global_confirm {
179 TAILQ_ENTRY(global_confirm) entry;
180 global_confirm_cb *cb;
181 void *ctx;
182 int ref_count;
183};
184TAILQ_HEAD(global_confirms, global_confirm);
185static struct global_confirms global_confirms =
186 TAILQ_HEAD_INITIALIZER(global_confirms);
187
177/*XXX*/ 188/*XXX*/
178extern Kex *xxx_kex; 189extern Kex *xxx_kex;
179 190
@@ -468,8 +479,19 @@ client_check_window_change(void)
468static void 479static void
469client_global_request_reply(int type, u_int32_t seq, void *ctxt) 480client_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
475static void 497static 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
729void
730client_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
705static void 750static void
706process_cmdline(void) 751process_cmdline(void)
707{ 752{