From 77774e96ef3f5011bb85f7e0ec68a7f3a4a4d6e8 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 28 Apr 2014 22:42:43 +0300 Subject: [PATCH] silcclient: Add generic client entry operation context Add generic client entry async operation context to the internal context. Change the key agreement to start using it. Add support for aborting client entry operations when the client entry is deleted or when the connection is closed to the server. --- lib/silcclient/client.c | 17 +++++++++++++++++ lib/silcclient/client.h | 3 ++- lib/silcclient/client_connect.c | 2 +- lib/silcclient/client_entry.c | 13 ++++++++++++- lib/silcclient/client_keyagr.c | 32 +++++++++++++++++--------------- lib/silcclient/client_listener.c | 2 +- 6 files changed, 50 insertions(+), 19 deletions(-) diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 38afc453..f72a4a72 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -391,6 +391,9 @@ SILC_FSM_STATE(silc_client_connection_st_close) { SilcClientConnection conn = fsm_context; SilcClientCommandContext cmd; + SilcList list; + SilcIDCacheEntry entry; + SilcClientEntry client_entry; /* Finish running command threads. This will also finish waiting packet thread, as they are always waiting for some command. If any thread is @@ -416,6 +419,20 @@ SILC_FSM_STATE(silc_client_connection_st_close) conn->internal->op = NULL; } + /* Abort ongoing client entry operations */ + if (conn->internal->client_cache) { + if (silc_idcache_get_all(conn->internal->client_cache, &list)) { + silc_list_start(list); + while ((entry = silc_list_get(list))) { + client_entry = entry->context; + if (client_entry->internal.op) { + silc_async_abort(client_entry->internal.op, NULL, NULL); + client_entry->internal.op = NULL; + } + } + } + } + /* If event thread is running, finish it. */ if (silc_fsm_is_started(&conn->internal->event_thread)) { SILC_LOG_DEBUG(("Finish event thread")); diff --git a/lib/silcclient/client.h b/lib/silcclient/client.h index 8c989553..019bd3c2 100644 --- a/lib/silcclient/client.h +++ b/lib/silcclient/client.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2014 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,6 +52,7 @@ typedef struct SilcClientEntryInternalStruct { unsigned char *key; /* Valid if application provided the key */ SilcUInt32 key_len; /* Key data length */ SilcClientKeyAgreement ke; /* Current key agreement context or NULL */ + SilcAsyncOperation op; /* Asynchronous operation with this client */ SilcAtomic32 refcnt; /* Reference counter */ SilcAtomic32 deleted; /* Flag indicating whether the client object is diff --git a/lib/silcclient/client_connect.c b/lib/silcclient/client_connect.c index fd0e5462..de877d54 100644 --- a/lib/silcclient/client_connect.c +++ b/lib/silcclient/client_connect.c @@ -468,7 +468,7 @@ SILC_FSM_STATE(silc_client_st_connect_key_exchange) { SilcClientConnection conn = fsm_context; SilcClient client = conn->client; - SilcSKEParamsStruct params; + SilcSKEParamsStruct params = {}; SilcClientID cid; SILC_LOG_DEBUG(("Starting key exchange protocol")); diff --git a/lib/silcclient/client_entry.c b/lib/silcclient/client_entry.c index 2a94f11b..0639c04d 100644 --- a/lib/silcclient/client_entry.c +++ b/lib/silcclient/client_entry.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2008 Pekka Riikonen + Copyright (C) 2001 - 2014 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1007,6 +1007,9 @@ void silc_client_del_client_entry(SilcClient client, if (client_entry->internal.hmac_receive) silc_hmac_free(client_entry->internal.hmac_receive); silc_client_ftp_session_free_client(client, client_entry); + if (client_entry->internal.op) + silc_async_abort(client_entry->internal.op, NULL, NULL); + client_entry->internal.op = NULL; if (client_entry->internal.ke) silc_client_abort_key_agreement(client, conn, client_entry); silc_atomic_uninit32(&client_entry->internal.deleted); @@ -1030,6 +1033,14 @@ SilcBool silc_client_del_client(SilcClient client, SilcClientConnection conn, return FALSE; } + /* Abort ongoing operation */ + if (client_entry->internal.op) { + SILC_LOG_DEBUG(("Aborting ongoing operation %p", + client_entry->internal.op)); + silc_async_abort(client_entry->internal.op, NULL, NULL); + client_entry->internal.op = NULL; + } + silc_client_unref_client(client, conn, client_entry); return TRUE; } diff --git a/lib/silcclient/client_keyagr.c b/lib/silcclient/client_keyagr.c index 0d0ef8b4..24d13437 100644 --- a/lib/silcclient/client_keyagr.c +++ b/lib/silcclient/client_keyagr.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2007 Pekka Riikonen + Copyright (C) 2001 - 2014 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,7 +30,6 @@ struct SilcClientKeyAgreementStruct { SilcClientListener listener; /* Listener */ SilcKeyAgreementCallback completion; /* Key agreement completion */ void *context; /* User context */ - SilcAsyncOperation op; /* Async operation, initiator */ }; /************************ Static utility functions **************************/ @@ -45,8 +44,9 @@ static void silc_client_keyagr_free(SilcClient client, silc_client_listener_free(ke->listener); silc_schedule_task_del_by_context(conn->internal->schedule, client_entry); - if (ke->op) - silc_async_abort(ke->op, NULL, NULL); + if (client_entry->internal.op) + silc_async_abort(client_entry->internal.op, NULL, NULL); + client_entry->internal.op = NULL; client_entry->internal.ke = NULL; client_entry->internal.prv_resp = FALSE; silc_client_unref_client(client, conn, client_entry); @@ -103,7 +103,7 @@ static void silc_client_keyagr_completion(SilcClient client, SilcClientKeyAgreement ke = client_entry->internal.ke; SilcSKEKeyMaterial keymat; - ke->op = NULL; + client_entry->internal.op = NULL; switch (status) { case SILC_CLIENT_CONN_SUCCESS: @@ -280,11 +280,12 @@ void silc_client_perform_key_agreement(SilcClient client, params->no_authentication = TRUE; /* Connect to the remote client. Performs key exchange automatically. */ - ke->op = silc_client_connect_to_client(client, params, public_key, - private_key, hostname, port, - silc_client_keyagr_completion, - client_entry); - if (!ke->op) { + client_entry->internal.op = + silc_client_connect_to_client(client, params, public_key, + private_key, hostname, port, + silc_client_keyagr_completion, + client_entry); + if (!client_entry->internal.op) { completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR, NULL, context); silc_client_keyagr_free(client, conn, client_entry); @@ -338,11 +339,12 @@ silc_client_perform_key_agreement_stream(SilcClient client, params->no_authentication = TRUE; /* Perform key exchange protocol */ - ke->op = silc_client_key_exchange(client, params, public_key, - private_key, stream, SILC_CONN_CLIENT, - silc_client_keyagr_completion, - client_entry); - if (!ke->op) { + client_entry->internal.op = + silc_client_key_exchange(client, params, public_key, + private_key, stream, SILC_CONN_CLIENT, + silc_client_keyagr_completion, + client_entry); + if (!client_entry->internal.op) { completion(client, conn, client_entry, SILC_KEY_AGREEMENT_ERROR, NULL, context); silc_client_keyagr_free(client, conn, client_entry); diff --git a/lib/silcclient/client_listener.c b/lib/silcclient/client_listener.c index d6af269f..37b9d8f4 100644 --- a/lib/silcclient/client_listener.c +++ b/lib/silcclient/client_listener.c @@ -151,7 +151,7 @@ silc_client_listener_new_connection(SilcClientListener listener, { SilcClient client = listener->client; SilcClientConnection conn; - SilcSKEParamsStruct params; + SilcSKEParamsStruct params = {}; const char *hostname = NULL, *ip = NULL; SilcUInt16 port; -- 2.24.0