updates.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 12 Jul 2001 09:23:15 +0000 (09:23 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 12 Jul 2001 09:23:15 +0000 (09:23 +0000)
CHANGES
TODO
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/server.c

diff --git a/CHANGES b/CHANGES
index fe7056cda64839569db99f879ca91e43101c3a30..47158a730569561a8560169e48cba5420fd084d4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,18 @@
+Thu Jul 12 10:18:40 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
+
+       * Do not cancel the protocol in silc_server_close_connection
+         it might cause recursion.  Now cancelled in the function
+         silc_server_free_sock_user_data.  Affected file silcd/server.c.
+
+       * Fixed the silc_server_remove_clients_by_server to regenerate
+         the channel keys correctly finally.  Added also new function
+         silc_server_remove_clients_channels to actually do it.
+         Affected file silcd/server.c.
+
+       * Fixed the silc_server_new_channel to not crash by giving
+         wrong router to the new channel.  Affected file is
+         silcd/packet_receive.c.
+
 Wed Jul 11 18:31:57 EEST 2001  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SilcClientParams structure to the lib/silcclient/silcapi.h
diff --git a/TODO b/TODO
index 4f205059f5cc2365d2854cc5ebe62039f43d717e..c6fce455fad2c4b66b3c61f710d7add4be9fee4c 100644 (file)
--- a/TODO
+++ b/TODO
@@ -5,6 +5,11 @@ TODO/bugs in Irssi SILC client
    cipher, hash, hmac and pkcs configuration to the Irssi SILC's config
    file.
 
+ o Add local command to switch the channel's private key when channel has
+   several private keys.  Currently sending channel messages with many
+   keys is not possible because changing the key is not possible by the
+   user.
+
  o Add local commands to list the current server and client public keys
    that the user has.  And a local command to dump the contents of the
    public key to the screen.  Something like LISTKEYS, SHOWKEY...
index bdb236d3cbeb25a69869b00843f4ee407e7a0272..14a6550fa6b02dda1c7313b28970c7547fa3bf34 100644 (file)
@@ -4798,11 +4798,11 @@ SILC_SERVER_CMD_FUNC(users)
       return;
     }
 
-    /* We are router and we will check the global list as well. */
+    /* Check the global list as well. */
     if (id)
       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
     else
-      channel = silc_idlist_find_channel_by_name(server->local_list, 
+      channel = silc_idlist_find_channel_by_name(server->global_list, 
                                                 channel_name, NULL);
     if (!channel) {
       /* Channel really does not exist */
index be1ee659804362d3b35ec4024f44c46295d076ee..83a9348fe21aa0ed9076bacfaad5d4f3ab629436 100644 (file)
@@ -1872,7 +1872,7 @@ void silc_server_new_channel(SilcServer server,
                    sock->hostname));
     
     silc_idlist_add_channel(server->global_list, strdup(channel_name), 
-                           0, channel_id, server->router->connection
+                           0, channel_id, sock->user_data
                            NULL, NULL);
 
     server->stat.channels++;
index 38f645e49338ac19068edc549ff44c093e289f82..91ee0291b11773c10297347b5c5ccbb296b1e4e1 100644 (file)
@@ -2114,14 +2114,6 @@ void silc_server_close_connection(SilcServer server,
                  sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
                  "Router"), sock->sock));
 
-  /* If any protocol is active cancel its execution */
-  if (sock->protocol) {
-    silc_protocol_cancel(sock->protocol, server->timeout_queue);
-    sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
-    silc_protocol_execute_final(sock->protocol, server->timeout_queue);
-    sock->protocol = NULL;
-  }
-
   /* We won't listen for this connection anymore */
   silc_schedule_unset_listen_fd(server->schedule, sock->sock);
 
@@ -2300,9 +2292,118 @@ void silc_server_free_sock_user_data(SilcServer server,
     }
   }
 
+  /* If any protocol is active cancel its execution */
+  if (sock->protocol) {
+    silc_protocol_cancel(sock->protocol, server->timeout_queue);
+    sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+    silc_protocol_execute_final(sock->protocol, server->timeout_queue);
+    sock->protocol = NULL;
+  }
+
   sock->user_data = NULL;
 }
 
+/* Removes the client from channels and possibly removes the channels
+   as well.  After removing those channels that exist, their channel
+   keys are regnerated. This is called only by the function
+   silc_server_remove_clients_by_server. */
+
+static void silc_server_remove_clients_channels(SilcServer server, 
+                                               SilcSocketConnection sock,
+                                               SilcClientEntry client,
+                                               SilcHashTable channels)
+{
+  SilcChannelEntry channel;
+  SilcChannelClientEntry chl;
+  SilcHashTableList htl;
+  SilcBuffer clidp;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (!client || !client->id)
+    return;
+
+  clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+
+  /* Remove the client from all channels. The client is removed from
+     the channels' user list. */
+  silc_hash_table_list(client->channels, &htl);
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
+    channel = chl->channel;
+
+    /* Remove channel from client's channel list */
+    silc_hash_table_del(client->channels, channel);
+
+    /* Remove channel if there is no users anymore */
+    if (server->server_type == SILC_ROUTER &&
+       silc_hash_table_count(channel->user_list) < 2) {
+
+      if (silc_hash_table_find(channels, channel, NULL, NULL))
+       silc_hash_table_del(channels, channel);
+
+      if (channel->rekey)
+       silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
+
+      if (!silc_idlist_del_channel(server->local_list, channel))
+       silc_idlist_del_channel(server->global_list, channel);
+      server->stat.my_channels--;
+      continue;
+    }
+
+    /* Remove client from channel's client list */
+    silc_hash_table_del(channel->user_list, chl->client);
+    silc_free(chl);
+    server->stat.my_chanclients--;
+
+    /* If there is no global users on the channel anymore mark the channel
+       as local channel. Do not check if the removed client is local client. */
+    if (server->server_type == SILC_SERVER && channel->global_users && 
+       chl->client->router && !silc_server_channel_has_global(channel))
+      channel->global_users = FALSE;
+
+    /* If there is not at least one local user on the channel then we don't
+       need the channel entry anymore, we can remove it safely. */
+    if (server->server_type == SILC_SERVER &&
+       !silc_server_channel_has_local(channel)) {
+
+      if (silc_hash_table_find(channels, channel, NULL, NULL))
+       silc_hash_table_del(channels, channel);
+
+      if (channel->rekey)
+       silc_task_unregister_by_context(server->timeout_queue, channel->rekey);
+
+      if (channel->founder_key) {
+       /* The founder auth data exists, do not remove the channel entry */
+       SilcChannelClientEntry chl2;
+       SilcHashTableList htl2;
+
+       channel->id = NULL;
+
+       silc_hash_table_list(channel->user_list, &htl2);
+       while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
+         silc_hash_table_del(chl2->client->channels, channel);
+         silc_hash_table_del(channel->user_list, chl2->client);
+         silc_free(chl2);
+       }
+       continue;
+      }
+
+      /* Remove the channel entry */
+      if (!silc_idlist_del_channel(server->local_list, channel))
+       silc_idlist_del_channel(server->global_list, channel);
+      server->stat.my_channels--;
+      continue;
+    }
+
+    /* Add the channel to the the channels list to regenerate the 
+       channel key */
+    if (!silc_hash_table_find(channels, channel, NULL, NULL))
+      silc_hash_table_add(channels, channel, channel);
+  }
+
+  silc_buffer_free(clidp);
+}
+
 /* This function is used to remove all client entries by the server `entry'.
    This is called when the connection is lost to the server. In this case
    we must invalidate all the client entries owned by the server `entry'. 
@@ -2321,10 +2422,9 @@ int silc_server_remove_clients_by_server(SilcServer server,
   uint32 clients_c = 0;
   unsigned char **argv = NULL;
   uint32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
-  SilcHashTable channels;
-  SilcChannelClientEntry chl;
-  SilcChannelEntry channel;
   SilcHashTableList htl;
+  SilcChannelEntry channel;
+  SilcHashTable channels;
   int i;
 
   SILC_LOG_DEBUG(("Start"));
@@ -2389,16 +2489,8 @@ int silc_server_remove_clients_by_server(SilcServer server,
          silc_buffer_free(idp);
        }
 
-       silc_hash_table_list(client->channels, &htl);
-       while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
-         if (silc_hash_table_find(channels, chl->channel, NULL, NULL))
-           continue;
-         silc_hash_table_add(channels, chl->channel, chl->channel);
-       }
-
        /* Remove the client entry */
-       silc_server_remove_from_channels(server, NULL, client, FALSE, 
-                                        NULL, FALSE);
+       silc_server_remove_clients_channels(server, NULL, client, channels);
        silc_idlist_del_client(server->local_list, client);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -2449,16 +2541,8 @@ int silc_server_remove_clients_by_server(SilcServer server,
          silc_buffer_free(idp);
        }
 
-       silc_hash_table_list(client->channels, &htl);
-       while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
-         if (silc_hash_table_find(channels, chl->channel, NULL, NULL))
-           continue;
-         silc_hash_table_add(channels, chl->channel, chl->channel);
-       }
-
        /* Remove the client entry */
-       silc_server_remove_from_channels(server, NULL, client, FALSE,
-                                        NULL, FALSE);
+       silc_server_remove_clients_channels(server, NULL, client, channels);
        silc_idlist_del_client(server->global_list, client);
 
        if (!silc_idcache_list_next(list, &id_cache))