updates.
[silc.git] / lib / silcclient / client_notify.c
index 49c315c51fc46e5cddd0c3230447885d822776c4..d2895494df7f8a7bed4a4ecfc17ea399e92f7334 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  client_notify.c
+  client_notify.c 
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2002 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
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -41,25 +40,20 @@ static void silc_client_notify_by_server_pending(void *context, void *context2)
   SilcClientCommandReplyContext reply = 
     (SilcClientCommandReplyContext)context2;
 
+  SILC_LOG_DEBUG(("Start"));
+
   if (reply) {
     SilcCommandStatus status;
     unsigned char *tmp = silc_argument_get_arg_type(reply->args, 1, NULL);
     SILC_GET16_MSB(status, tmp);
-    if (status != SILC_STATUS_OK) {
-      silc_socket_free(res->sock);
-      return;
-    }
+    if (status != SILC_STATUS_OK)
+      goto out;
   }
 
   silc_client_notify_by_server(res->context, res->sock, res->packet);
-  silc_socket_free(res->sock);
-}
-
-/* Destructor for the pending command callback */
 
-static void silc_client_notify_by_server_destructor(void *context)
-{
-  SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
+ out:
+  silc_socket_free(res->sock);
   silc_packet_context_free(res->packet);
   silc_free(res);
 }
@@ -84,7 +78,6 @@ static void silc_client_notify_by_server_resolve(SilcClient client,
   silc_client_command_send(client, conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
                           1, 3, idp->data, idp->len);
   silc_client_command_pending(conn, SILC_COMMAND_WHOIS, conn->cmd_ident,
-                             silc_client_notify_by_server_destructor,
                              silc_client_notify_by_server_pending, res);
   silc_buffer_free(idp);
 }
@@ -472,26 +465,37 @@ void silc_client_notify_by_server(SilcClient client,
     /* Find Client entry and if not found resolve it */
     client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
     if (!client_entry2) {
+      /* Resolve the entry information */
       silc_client_notify_by_server_resolve(client, conn, packet, client_id);
-      goto out;
+
+      /* Add the new entry even though we resolved it. This is because we
+        want to replace the old entry with the new entry here right now. */
+      client_entry2 = 
+       silc_client_add_client(client, conn, NULL, NULL, NULL, 
+                              silc_id_dup(client_id, SILC_ID_CLIENT), 
+                              client_entry->mode);
+
+      /* Replace old ID entry with new one on all channels. */
+      silc_client_replace_from_channels(client, conn, client_entry,
+                                       client_entry2);
     } else {
       if (client_entry2 != conn->local_entry)
        silc_client_nickname_format(client, conn, client_entry2);
-    }
 
-    /* Remove the old from cache */
-    silc_idcache_del_by_context(conn->client_cache, client_entry);
+      /* Remove the old from cache */
+      silc_idcache_del_by_context(conn->client_cache, client_entry);
 
-    /* Replace old ID entry with new one on all channels. */
-    silc_client_replace_from_channels(client, conn, client_entry,
-                                     client_entry2);
+      /* Replace old ID entry with new one on all channels. */
+      silc_client_replace_from_channels(client, conn, client_entry,
+                                       client_entry2);
 
-    /* Notify application */
-    client->internal->ops->notify(client, conn, type, 
-                                 client_entry, client_entry2);
+      /* Notify application */
+      client->internal->ops->notify(client, conn, type, 
+                                   client_entry, client_entry2);
 
-    /* Free data */
-    silc_client_del_client_entry(client, conn, client_entry);
+      /* Free data */
+      silc_client_del_client_entry(client, conn, client_entry);
+    }
     break;
 
   case SILC_NOTIFY_TYPE_CMODE_CHANGE:
@@ -838,11 +842,9 @@ void silc_client_notify_by_server(SilcClient client,
     /* Notify application. */
     client->internal->ops->notify(client, conn, type, client_entry, tmp);
 
-    if (client_entry != conn->local_entry) {
-      /* Remove client from all channels */
-      silc_client_remove_from_channels(client, conn, client_entry);
+    if (client_entry != conn->local_entry)
+      /* Remove the client from all channels and free it */
       silc_client_del_client(client, conn, client_entry);
-    }
 
     break;
     
@@ -891,7 +893,7 @@ void silc_client_notify_by_server(SilcClient client,
        if (client_entry == conn->local_entry)
          continue;
 
-       silc_client_remove_from_channels(client, conn, client_entry);
+       /* Remove the client from all channels and free it */
        silc_client_del_client(client, conn, client_entry);
       }
       silc_free(clients);