Resolve client info after LEAVE notify.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 2 Apr 2002 12:55:03 +0000 (12:55 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 2 Apr 2002 12:55:03 +0000 (12:55 +0000)
lib/silcclient/client_notify.c
lib/silcclient/idlist.c

index 5e13bf72dae90ce0c3860c576b47d06796dac597..1f9d56e18b8e10a15aebfca41583c13e840c1f6e 100644 (file)
 #include "silcclient.h"
 #include "client_internal.h"
 
+/* Context used for resolving client, channel and server info. */
 typedef struct {
-  SilcPacketContext *packet;
+  void *packet;
   void *context;
   SilcSocketConnection sock;
 } *SilcClientNotifyResolve;
 
+SILC_TASK_CALLBACK(silc_client_notify_check_client)
+{ 
+  SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
+  SilcClientConnection conn = res->context;
+  SilcClient client = conn->client;
+  SilcClientID *client_id = res->packet;
+  silc_client_get_client_by_id_resolve(client, conn, client_id, NULL, NULL);
+  silc_free(client_id);
+  silc_free(res);
+}
+
 /* Called when notify is received and some async operation (such as command)
    is required before processing the notify message. This calls again the
    silc_client_notify_by_server and reprocesses the original notify packet. */
@@ -72,7 +84,7 @@ static void silc_client_notify_by_server_resolve(SilcClient client,
   res->context = client;
   res->sock = silc_socket_dup(conn->sock);
 
-  /* For client resolving use WHOIS, and oterhwise use IDENTIFY */
+  /* For client resolving use WHOIS, and otherwise use IDENTIFY */
   if (id_type == SILC_ID_CLIENT) {
     silc_client_command_register(client, SILC_COMMAND_WHOIS, NULL, NULL,
                                 silc_client_command_reply_whois_i, 0,
@@ -292,6 +304,20 @@ void silc_client_notify_by_server(SilcClient client,
       silc_free(chu);
     }
 
+    /* Some client implementations actually quit network by first doing
+       LEAVE and then immediately SIGNOFF.  We'll check for this by doing 
+       check for the client after 15 seconds.  If it is not valid after
+       that we'll remove the client from cache. */
+    if (!silc_hash_table_count(client_entry->channels)) {
+      SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
+      res->context = conn;
+      res->packet = silc_id_dup(client_id, SILC_ID_CLIENT);
+      silc_schedule_task_add(client->schedule, 0,
+                            silc_client_notify_check_client, conn,
+                            15, 0, SILC_TASK_TIMEOUT, 
+                            SILC_TASK_PRI_NORMAL);
+    }
+
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
index 15455b69d509f46cdb74b353692475eab9429d0b..7549a62ddfb12826517b00548674820306533f36 100644 (file)
@@ -506,10 +506,13 @@ SILC_CLIENT_CMD_FUNC(get_client_by_id_callback)
 
   /* Get the client */
   entry = silc_client_get_client_by_id(i->client, i->conn, i->client_id);
-  if (entry)
-    i->completion(i->client, i->conn, &entry, 1, i->context);
-  else
-    i->completion(i->client, i->conn, NULL, 0, i->context);
+  if (entry) {
+    if (i->completion)
+      i->completion(i->client, i->conn, &entry, 1, i->context);
+  } else {
+    if (i->completion)
+      i->completion(i->client, i->conn, NULL, 0, i->context);
+  }
 
   silc_free(i->client_id);
   silc_free(i);