From 84e77804f1b96b59cb3c23a6d4e2c80361ee6135 Mon Sep 17 00:00:00 2001 From: piaip Date: Thu, 18 Jun 2009 09:52:04 +0000 Subject: * fix: if connection was closed before being acked, the ack should be abandoned directly. git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4658 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- daemon/logind/logind.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'daemon') diff --git a/daemon/logind/logind.c b/daemon/logind/logind.c index 4e8149ef..e2e66db5 100644 --- a/daemon/logind/logind.c +++ b/daemon/logind/logind.c @@ -391,7 +391,9 @@ ackq_del(login_conn_ctx *conn) { size_t i; - assert(conn && conn->cb == sizeof(login_conn_ctx)); + // XXX in current implementation, the conn pointer may be + // destroyed before getting acks, so don't check its validness. + // assert(conn && conn->cb == sizeof(login_conn_ctx)); for (i = 0; i < g_ack_queue.size; i++) { if (g_ack_queue.queue[i] != conn) @@ -1465,24 +1467,29 @@ ack_cb(int tunnel, short event, void *arg) return; } - if (conn->cb != sizeof(login_conn_ctx)) + // some connections may be removed (for example, socket close) before being acked. + // XXX FIXME if someone created a new connection before ack comes and re-used + // the memory location of previous destroyed one, we'd have problem here. + if (!ackq_del(conn)) { - fprintf(stderr, LOG_PREFIX "warning: tunnel returned invalid ack. abort?\r\n"); - // assert(conn && conn->cb == sizeof(login_conn_ctx)); + if (g_verbose > VERBOSE_ERROR) fprintf(stderr, LOG_PREFIX + "drop abandoned ack connection: %p.\r\n", conn); return; } - // XXX success connection. - if (ackq_del(conn)) + // check connection + if (conn->cb != sizeof(login_conn_ctx)) { - // reset the state to prevent processing ackq again - conn->ctx.state = LOGIN_STATE_AUTH; - // this event is still in queue. - login_conn_remove(conn, conn->telnet.fd, 0); - } else { - if (g_verbose > VERBOSE_ERROR) fprintf(stderr, LOG_PREFIX - "got invalid ack connection: %p.\r\n", conn); + fprintf(stderr, LOG_PREFIX + "warning: received invalid ack from tunnel. abort/reset tunnel?\r\n"); + // assert(conn && conn->cb == sizeof(login_conn_ctx)); + return; } + + // reset the state to prevent processing ackq again + conn->ctx.state = LOGIN_STATE_AUTH; + // this event is still in queue. + login_conn_remove(conn, conn->telnet.fd, 0); } -- cgit v1.2.3