More client library rewrites (added rekey)
[silc.git] / lib / silcclient / client_notify.c
index 206425dc9379d212964bc48a5a415d708450f415..068b22d5926560c9dc9c9389a27f3e85eb96c8d1 100644 (file)
@@ -238,6 +238,8 @@ SILC_FSM_STATE(silc_client_notify_none)
   SilcNotifyType type = silc_notify_get_type(payload);
   SilcArgumentPayload args = silc_notify_get_args(payload);
 
+  SILC_LOG_DEBUG(("Notify: NONE"));
+
   /* Notify application */
   NOTIFY(client, conn, type, silc_argument_get_arg_type(args, 1, NULL));
 
@@ -380,7 +382,7 @@ SILC_FSM_STATE(silc_client_notify_join)
     silc_client_nickname_format(client, conn, client_entry);
 
   /* Join the client to channel */
-  if (!silc_client_add_to_channel(channel, client_entry, 0))
+  if (!silc_client_add_to_channel(client, conn, channel, client_entry, 0))
     goto out;
 
   /* Notify application. */
@@ -410,7 +412,6 @@ SILC_FSM_STATE(silc_client_notify_leave)
   SilcArgumentPayload args = silc_notify_get_args(payload);
   SilcClientEntry client_entry = NULL;
   SilcChannelEntry channel = NULL;
-  SilcChannelUser chu;
   SilcID id;
 
   SILC_LOG_DEBUG(("Notify: LEAVE"));
@@ -444,30 +445,7 @@ SILC_FSM_STATE(silc_client_notify_leave)
     goto out;
 
   /* Remove client from channel */
-  chu = silc_client_on_channel(channel, client_entry);
-  if (chu) {
-    silc_hash_table_del(client_entry->channels, channel);
-    silc_hash_table_del(channel->user_list, client_entry);
-    silc_free(chu);
-  }
-
-#if 0 /* Kind of useless, server will return error if client keeps using
-        non-existing client, and the entry is removed then. */
-  /* 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 5 - 34 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 = client;
-    res->sock = silc_socket_dup(conn->sock);
-    res->packet = silc_id_dup(client_id, SILC_ID_CLIENT);
-    silc_schedule_task_add(client->schedule, conn->sock->sock,
-                          silc_client_notify_check_client, res,
-                          (5 + (silc_rng_get_rn16(client->rng) % 29)),
-                          0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-  }
-#endif
+  silc_client_remove_from_channel(client, conn, channel, client_entry);
 
   /* Notify application. */
   NOTIFY(client, conn, type, client_entry, channel);
@@ -517,17 +495,10 @@ SILC_FSM_STATE(silc_client_notify_signoff)
   /* Notify application */
   NOTIFY(client, conn, type, client_entry, tmp);
 
-  /* Remove from all channels */
+  /* Delete client */
   silc_client_remove_from_channels(client, conn, client_entry);
-
-#if 0
-  /* Remove from cache */
-  silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
-#endif
-
-  /* Free data */
+  silc_client_del_client(client, conn, client_entry);
   silc_client_unref_client(client, conn, client_entry);
-  silc_client_del_client_entry(client, conn, client_entry);
 
  out:
   /** Notify processed */
@@ -713,9 +684,10 @@ SILC_FSM_STATE(silc_client_notify_nick_change)
       silc_utf8_strcasecmp(tmp, client_entry->nickname)) {
     /* Nickname didn't change.  Update only Client ID.  We don't notify
        application because nickname didn't change. */
-    silc_idcache_update(conn->internal->client_cache, client_entry,
-                       &client_entry->id, &id2.u.client_id, NULL,
-                       NULL, FALSE);
+    silc_mutex_lock(conn->internal->lock);
+    silc_idcache_update_by_context(conn->internal->client_cache, client_entry,
+                                  &id2.u.client_id, NULL, FALSE);
+    silc_mutex_unlock(conn->internal->lock);
     goto out;
   }
 
@@ -725,12 +697,14 @@ SILC_FSM_STATE(silc_client_notify_nick_change)
     goto out;
 
   /* Update nickname */
-  if (!silc_idcache_update(conn->internal->client_cache, client_entry,
-                          NULL, NULL, client_entry->nickname_normalized,
-                          nick, TRUE)) {
+  silc_mutex_lock(conn->internal->lock);
+  if (!silc_idcache_update_by_context(conn->internal->client_cache,
+                                     client_entry, NULL, nick, TRUE)) {
     silc_free(nick);
+    silc_mutex_unlock(conn->internal->lock);
     goto out;
   }
+  silc_mutex_unlock(conn->internal->lock);
   memcpy(oldnick, client_entry->nickname, sizeof(client_entry->nickname));
   memcpy(client_entry->nickname, tmp, tmp_len);
   client_entry->nickname_normalized = nick;
@@ -967,6 +941,22 @@ SILC_FSM_STATE(silc_client_notify_cumode_change)
     /* NOT REACHED */
   }
 
+  /* Get target Client ID */
+  if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id2, NULL))
+    goto out;
+
+  /* Find target Client entry */
+  client_entry2 = silc_client_get_client_by_id(client, conn, &id2.u.client_id);
+  if (!client_entry2 || !client_entry2->nickname[0]) {
+    /** Resolve client */
+    silc_client_unref_client(client, conn, client_entry2);
+    SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
+                                        client, conn, &id2.u.client_id, NULL,
+                                        silc_client_notify_resolved,
+                                        notify));
+    /* NOT REACHED */
+  }
+
   /* Get the mode */
   tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
   if (!tmp)
@@ -1023,23 +1013,6 @@ SILC_FSM_STATE(silc_client_notify_cumode_change)
     entry = channel_entry;
   }
 
-  /* Get target Client ID */
-  if (!silc_argument_get_decoded(args, 3, SILC_ARGUMENT_ID, &id2, NULL))
-    goto out;
-
-  /* Find target Client entry */
-  client_entry2 = silc_client_get_client_by_id(client, conn, &id2.u.client_id);
-  if (!client_entry2 || !client_entry2->nickname[0]) {
-    /** Resolve client */
-    silc_client_unref_client(client, conn, client_entry);
-    silc_client_unref_client(client, conn, client_entry2);
-    SILC_FSM_CALL(silc_client_get_client_by_id_resolve(
-                                        client, conn, &id2.u.client_id, NULL,
-                                        silc_client_notify_resolved,
-                                        notify));
-    /* NOT REACHED */
-  }
-
   /* Save the mode */
   chu = silc_client_on_channel(channel, client_entry2);
   if (chu)
@@ -1164,7 +1137,6 @@ SILC_FSM_STATE(silc_client_notify_kicked)
   SilcArgumentPayload args = silc_notify_get_args(payload);
   SilcClientEntry client_entry, client_entry2;
   SilcChannelEntry channel = NULL;
-  SilcChannelUser chu;
   unsigned char *tmp;
   SilcUInt32 tmp_len;
   SilcID id;
@@ -1222,14 +1194,8 @@ SILC_FSM_STATE(silc_client_notify_kicked)
   tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
 
   /* Remove kicked client from channel */
-  if (client_entry != conn->local_entry) {
-    chu = silc_client_on_channel(channel, client_entry);
-    if (chu) {
-      silc_hash_table_del(client_entry->channels, channel);
-      silc_hash_table_del(channel->user_list, client_entry);
-      silc_free(chu);
-    }
-  }
+  if (client_entry != conn->local_entry)
+    silc_client_remove_from_channel(client, conn, channel, client_entry);
 
   /* Notify application. */
   NOTIFY(client, conn, type, client_entry, tmp, client_entry2, channel);
@@ -1238,6 +1204,7 @@ SILC_FSM_STATE(silc_client_notify_kicked)
   if (client_entry == conn->local_entry) {
     if (conn->current_channel == channel)
       conn->current_channel = NULL;
+    silc_client_empty_channel(client, conn, channel);
     silc_client_del_channel(client, conn, channel);
   }
 
@@ -1335,8 +1302,10 @@ SILC_FSM_STATE(silc_client_notify_killed)
   NOTIFY(client, conn, type, client_entry, comment, id.type, entry);
 
   /* Delete the killed client */
-  if (client_entry != conn->local_entry)
+  if (client_entry != conn->local_entry) {
+    silc_client_remove_from_channels(client, conn, client_entry);
     silc_client_del_client(client, conn, client_entry);
+  }
 
  out:
   silc_client_unref_client(client, conn, client_entry);
@@ -1369,7 +1338,7 @@ SILC_FSM_STATE(silc_client_notify_server_signoff)
   SilcID id;
   int i;
 
-  SILC_LOG_DEBUG(("Notify: SIGNOFF"));
+  SILC_LOG_DEBUG(("Notify: SERVER_SIGNOFF"));
 
   clients = silc_dlist_init();
   if (!clients)
@@ -1392,8 +1361,10 @@ SILC_FSM_STATE(silc_client_notify_server_signoff)
 
   /* Delete the clients */
   silc_dlist_start(clients);
-  while ((client_entry = silc_dlist_get(clients)))
+  while ((client_entry = silc_dlist_get(clients))) {
+    silc_client_remove_from_channels(client, conn, client_entry);
     silc_client_del_client(client, conn, client_entry);
+  }
 
  out:
   /** Notify processed */
@@ -1434,6 +1405,7 @@ SILC_FSM_STATE(silc_client_notify_error)
       goto out;
     client_entry = silc_client_get_client_by_id(client, conn, &id.u.client_id);
     if (client_entry) {
+      silc_client_remove_from_channels(client, conn, client_entry);
       silc_client_del_client(client, conn, client_entry);
       silc_client_unref_client(client, conn, client_entry);
     }
@@ -1544,8 +1516,10 @@ SILC_FSM_STATE(silc_client_notify_watch)
           ntype == SILC_NOTIFY_TYPE_KILLED)
     del_client = TRUE;
 
-  if (del_client)
+  if (del_client) {
+    silc_client_remove_from_channels(client, conn, client_entry);
     silc_client_del_client(client, conn, client_entry);
+  }
 
   if (public_key)
     silc_pkcs_public_key_free(public_key);