silcclient: Add generic client entry operation context
authorPekka Riikonen <priikone@silcnet.org>
Mon, 28 Apr 2014 19:42:43 +0000 (22:42 +0300)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 28 Apr 2014 19:42:43 +0000 (22:42 +0300)
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
lib/silcclient/client.h
lib/silcclient/client_connect.c
lib/silcclient/client_entry.c
lib/silcclient/client_keyagr.c
lib/silcclient/client_listener.c

index 38afc4537e297fb61f6ad6f1b88cc85c32571286..f72a4a7201ec64dba1f2b37f87457fbe1b81ebe6 100644 (file)
@@ -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"));
index 8c9895531c107ba906a4af6c2cd4e20adba61550..019bd3c23f4be5e65c9c2dfdd13996378c170667 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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
index fd0e546222c70a7dda14cc2673e0bdd566485927..de877d54dbfabd7c37081ccbf73deed948633b9e 100644 (file)
@@ -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"));
index 2a94f11bad3792b65d420b64de1ad436dba2677b..0639c04dfe37a04fea97063bc3da07f8953ca5d7 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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;
 }
index 0d0ef8b4481bbb23ece9d3da1672616174d80864..24d1343756e433cf9df71111573c69457342178a 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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);
index d6af269f65df0f19ff3fe6aaaf274e52b9d2f5fa..37b9d8f4f134b0b2bfe8f0ccce8fd2c1fc79a0da 100644 (file)
@@ -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;