diff --git a/mainchan.c b/mainchan.c index 14712615..320db2b9 100644 --- a/mainchan.c +++ b/mainchan.c @@ -334,33 +334,13 @@ static void mainchan_ready(mainchan *mc) queue_idempotent_callback(&mc->ppl->ic_process_queue); } -struct mainchan_open_failure_abort_ctx { - Ssh *ssh; - char *abort_message; -}; - -static void mainchan_open_failure_abort(void *vctx) -{ - struct mainchan_open_failure_abort_ctx *ctx = - (struct mainchan_open_failure_abort_ctx *)vctx; - ssh_sw_abort( - ctx->ssh, "Server refused to open main channel: %s", - ctx->abort_message); - sfree(ctx->abort_message); - sfree(ctx); -} - static void mainchan_open_failure(Channel *chan, const char *errtext) { assert(chan->vt == &mainchan_channelvt); mainchan *mc = container_of(chan, mainchan, chan); - struct mainchan_open_failure_abort_ctx *ctx = - snew(struct mainchan_open_failure_abort_ctx); - - ctx->ssh = mc->ppl->ssh; - ctx->abort_message = dupstr(errtext); - queue_toplevel_callback(mainchan_open_failure_abort, ctx); + ssh_sw_abort_deferred(mc->ppl->ssh, + "Server refused to open main channel: %s", errtext); } static size_t mainchan_send(Channel *chan, bool is_stderr, diff --git a/ssh.c b/ssh.c index 7e9ccd2b..a1f8d9ac 100644 --- a/ssh.c +++ b/ssh.c @@ -133,6 +133,8 @@ struct Ssh { Pinger *pinger; + char *deferred_abort_message; + bool need_random_unref; }; @@ -555,6 +557,24 @@ void ssh_user_close(Ssh *ssh, const char *fmt, ...) } } +void ssh_deferred_abort_callback(void *vctx) +{ + Ssh *ssh = (Ssh *)vctx; + char *msg = ssh->deferred_abort_message; + ssh->deferred_abort_message = NULL; + ssh_sw_abort(ssh, msg); + sfree(msg); +} + +void ssh_sw_abort_deferred(Ssh *ssh, const char *fmt, ...) +{ + if (!ssh->deferred_abort_message) { + GET_FORMATTED_MSG; + ssh->deferred_abort_message = msg; + queue_toplevel_callback(ssh_deferred_abort_callback, ssh); + } +} + static void ssh_socket_log(Plug *plug, int type, SockAddr *addr, int port, const char *error_msg, int error_code) { @@ -915,6 +935,8 @@ static void ssh_free(Backend *be) ssh_gss_cleanup(ssh->gss_state.libs); #endif + sfree(ssh->deferred_abort_message); + delete_callbacks_for_context(ssh); /* likely to catch ic_out_raw */ need_random_unref = ssh->need_random_unref; diff --git a/ssh.h b/ssh.h index cfd10746..b6dd71ec 100644 --- a/ssh.h +++ b/ssh.h @@ -407,6 +407,7 @@ void ssh_remote_error(Ssh *ssh, const char *fmt, ...); void ssh_remote_eof(Ssh *ssh, const char *fmt, ...); void ssh_proto_error(Ssh *ssh, const char *fmt, ...); void ssh_sw_abort(Ssh *ssh, const char *fmt, ...); +void ssh_sw_abort_deferred(Ssh *ssh, const char *fmt, ...); void ssh_user_close(Ssh *ssh, const char *fmt, ...); /* Bit positions in the SSH-1 cipher protocol word */