Some bugfixes.
authorPekka Riikonen <priikone@silcnet.org>
Thu, 2 Nov 2000 22:15:23 +0000 (22:15 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 2 Nov 2000 22:15:23 +0000 (22:15 +0000)
Changed server->sim to SilcDList and code accordingly.
Changes SilcClientEntry->channel to SilcList and added
back-pointer to SilcChannelClientEntry which is now used by both
client entry and channel entry

apps/silcd/command.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/server.c
apps/silcd/server_internal.h
apps/silcd/serverconfig.c

index dbad3bf3689fd06d372e94e038ce2deb4551a733..04901d7ef486390d0908c710ff24453a42355e78 100644 (file)
@@ -486,9 +486,10 @@ SILC_SERVER_CMD_FUNC(whois)
     
     silc_buffer_free(packet);
     silc_buffer_free(idp);
-    silc_free(clients);
   }
 
+  silc_free(clients);
+
   if (client_id)
     silc_free(client_id);
 
@@ -1387,27 +1388,15 @@ SILC_SERVER_CMD_FUNC(join)
     goto out;
   }
 
-  /* Join the client to the channel by adding it to channel's user list */
+  /* Join the client to the channel by adding it to channel's user list.
+     Add also the channel to client entry's channels list for fast cross-
+     referencing. */
   chl = silc_calloc(1, sizeof(*chl));
   chl->mode = umode;
   chl->client = client;
+  chl->channel = channel;
   silc_list_add(channel->user_list, chl);
-
-  /* Add the channel to client's channel list */
-  i = client->channel_count;
-  for (k = 0; k < client->channel_count; k++) {
-    if (client->channel[k] == NULL) {
-      client->channel[k] = channel;
-      break;
-    }
-  }
-  if (k >= i) {
-    i = client->channel_count;
-    client->channel = silc_realloc(client->channel, 
-                                  sizeof(*client->channel) * (i + 1));
-    client->channel[i] = channel;
-    client->channel_count++;
-  }
+  silc_list_add(client->channels, chl);
 
   /* Notify router about new user on channel. If we are normal server
      we send it to our router, if we are router we send it to our
index 358bef33f467826ace5549b419c4c4dc7652fcf5..0699c680a959c9fadf6da166f6edcff262eae1fc 100644 (file)
@@ -148,6 +148,8 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
   client->hmac = hmac;
   client->public_key = public_key;
   client->connection = connection;
+  silc_list_init(client->channels, struct SilcChannelClientEntryStruct, 
+                client_list);
 
   if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
                        (void *)client->id, (void *)client, TRUE)) {
@@ -378,7 +380,7 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
   channel->router = router;
   channel->channel_key = channel_key;
   silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct, 
-                next);
+                channel_list);
 
   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
                        SILC_ID_CHANNEL, (void *)channel->id, 
index aa444f46f59b78a92ad7f440f83780407bbf4ea2..51a143bbc4760c0e0fc3152a8e29ce82a13c84f6 100644 (file)
@@ -109,6 +109,44 @@ struct SilcServerEntryStruct {
   void *connection;
 };
 
+/* 
+   SILC Channel Client entry structure.
+
+   This entry used only by the SilcChannelEntry object and it holds
+   information about current clients (ie. users) on channel. Following
+   short description  of the fields:
+
+   SilcClientEntry client
+
+       Pointer to the client list. This is the client currently on channel.
+
+   unsigned int mode
+
+       Client's current mode on the channel.
+
+   SilcChannelEntry channel
+
+       Back pointer back to channel. As this structure is also used by
+       SilcClientEntry we have this here for fast access to the channel when
+       used by SilcClientEntry.
+
+  struct SilcChannelClientEntryStruct *client_list
+  struct SilcChannelClientEntryStruct *channel_list
+
+       List member pointers. This structure is used by channel entry and
+       client entry thus we must have separate list member pointers for
+       them since we are using same entry for both lists (the entry is not
+       duplicated). SilcList requires this.
+
+*/
+typedef struct SilcChannelClientEntryStruct {
+  SilcClientEntry client;
+  unsigned int mode;
+  SilcChannelEntry channel;
+  struct SilcChannelClientEntryStruct *client_list;
+  struct SilcChannelClientEntryStruct *channel_list;
+} *SilcChannelClientEntry;
+
 /* 
    SILC Client entry object.
 
@@ -233,8 +271,7 @@ struct SilcClientEntryStruct {
   SilcServerEntry router;
 
   /* List of channels client has joined to */
-  SilcChannelEntry *channel;
-  unsigned int channel_count;
+  SilcList channels;
 
   /* Keys */
   SilcCipher send_key;
@@ -247,28 +284,6 @@ struct SilcClientEntryStruct {
   void *connection;
 };
 
-/* 
-   SILC Channel Client entry structure.
-
-   This entry used only by the SilcChannelEntry object and it holds
-   information about current clients (ie. users) on channel. Following
-   short description  of the fields:
-
-   SilcClientEntry client
-
-       Pointer to the client list. This is the client currently on channel.
-
-   unsigned int mode
-
-       Client's current mode on the channel.
-
-*/
-typedef struct SilcChannelClientEntryStruct {
-  SilcClientEntry client;
-  unsigned int mode;
-  struct SilcChannelClientEntryStruct *next;
-} *SilcChannelClientEntry;
-
 /* 
    SILC Channel entry object.
 
index 3611f4293bb669032be1fcf6f3b2feab5c51dc31..149b34b963574d14593861624ed5396ead137537 100644 (file)
@@ -56,6 +56,9 @@ int silc_server_alloc(SilcServer *new_server)
   server->standalone = FALSE;
   server->local_list = silc_calloc(1, sizeof(*server->local_list));
   server->global_list = silc_calloc(1, sizeof(*server->global_list));
+#ifdef SILC_SIM
+  server->sim = silc_dlist_init();
+#endif
 
   *new_server = server;
 
@@ -68,6 +71,8 @@ int silc_server_alloc(SilcServer *new_server)
 void silc_server_free(SilcServer server)
 {
   if (server) {
+    SilcSimContext *sim;
+
     if (server->local_list)
       silc_free(server->local_list);
     if (server->global_list)
@@ -75,6 +80,12 @@ void silc_server_free(SilcServer server)
     if (server->rng)
       silc_rng_free(server->rng);
 
+    while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
+      silc_dlist_del(server->sim, sim);
+      silc_sim_free(sim);
+    }
+    silc_dlist_uninit(server->sim);
+
     silc_math_primegen_uninit(); /* XXX */
     silc_free(server);
   }
@@ -1786,7 +1797,6 @@ void silc_server_packet_send_to_channel(SilcServer server,
                                        unsigned int data_len,
                                        int force_send)
 {
-  int i;
   SilcSocketConnection sock = NULL;
   SilcPacketContext packetdata;
   SilcClientEntry client = NULL;
@@ -1875,8 +1885,6 @@ void silc_server_packet_send_to_channel(SilcServer server,
     /* Send to locally connected client */
     if (client) {
 
-      /* XXX Check client's mode on the channel. */
-
       /* Get data used in packet header encryption, keys and stuff. */
       sock = (SilcSocketConnection)client->connection;
       cipher = client->send_key;
@@ -1913,7 +1921,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
                                         unsigned int data_len,
                                         int force_send)
 {
-  int i, found = FALSE;
+  int found = FALSE;
   SilcSocketConnection sock = NULL;
   SilcPacketContext packetdata;
   SilcClientEntry client = NULL;
@@ -2051,7 +2059,6 @@ void silc_server_packet_send_local_channel(SilcServer server,
                                           unsigned int data_len,
                                           int force_send)
 {
-  int i;
   SilcClientEntry client;
   SilcChannelClientEntry chl;
   SilcSocketConnection sock = NULL;
@@ -2245,7 +2252,6 @@ void silc_server_remove_from_channels(SilcServer server,
                                      SilcSocketConnection sock,
                                      SilcClientEntry client)
 {
-  int i, k;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer chidp, clidp;
@@ -2259,52 +2265,43 @@ void silc_server_remove_from_channels(SilcServer server,
 
   /* Remove the client from all channels. The client is removed from
      the channels' user list. */
-  for (i = 0; i < client->channel_count; i++) {
-    channel = client->channel[i];
-    if (!channel)
-      continue;
-
+  silc_list_start(client->channels);
+  while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) {
+    channel = chl->channel;
     chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
 
-    /* Remove from channel */
-    silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-      if (chl->client == client) {
-
-       /* If this client is last one on the channel the channel
-          is removed all together. */
-       if (silc_list_count(channel->user_list) == 1) {
-
-         /* However, if the channel has marked global users then the 
-            channel is not created locally, and this does not remove the
-            channel globally from SILC network, in this case we will
-            notify that this client has left the channel. */
-         if (channel->global_users)
-           silc_server_send_notify_to_channel(server, channel,
-                                              SILC_NOTIFY_TYPE_SIGNOFF, 1,
-                                              clidp->data, clidp->len);
-
-         silc_idlist_del_channel(server->local_list, channel);
-         break;
-       }
+    /* Remove from list */
+    silc_list_del(client->channels, chl);
 
-       silc_list_del(channel->user_list, chl);
-       silc_free(chl);
+    /* If this client is last one on the channel the channel
+       is removed all together. */
+    if (silc_list_count(channel->user_list) < 2) {
 
-       /* Send notify to channel about client leaving SILC and thus
-          the entire channel. */
+      /* However, if the channel has marked global users then the 
+        channel is not created locally, and this does not remove the
+        channel globally from SILC network, in this case we will
+        notify that this client has left the channel. */
+      if (channel->global_users)
        silc_server_send_notify_to_channel(server, channel,
                                           SILC_NOTIFY_TYPE_SIGNOFF, 1,
                                           clidp->data, clidp->len);
-      }
+      
+      silc_idlist_del_channel(server->local_list, channel);
+      continue;
     }
 
+    /* Remove from list */
+    silc_list_del(channel->user_list, chl);
+    silc_free(chl);
+
+    /* Send notify to channel about client leaving SILC and thus
+       the entire channel. */
+    silc_server_send_notify_to_channel(server, channel,
+                                      SILC_NOTIFY_TYPE_SIGNOFF, 1,
+                                      clidp->data, clidp->len);
     silc_buffer_free(chidp);
   }
 
-  if (client->channel_count)
-    silc_free(client->channel);
-  client->channel = NULL;
   silc_buffer_free(clidp);
 }
 
@@ -2320,7 +2317,6 @@ int silc_server_remove_from_one_channel(SilcServer server,
                                        SilcClientEntry client,
                                        int notify)
 {
-  int i, k;
   SilcChannelEntry ch;
   SilcChannelClientEntry chl;
   SilcBuffer clidp;
@@ -2331,43 +2327,41 @@ int silc_server_remove_from_one_channel(SilcServer server,
 
   /* Remove the client from the channel. The client is removed from
      the channel's user list. */
-  for (i = 0; i < client->channel_count; i++) {
-    ch = client->channel[i];
-    if (!ch || ch != channel)
+  silc_list_start(client->channels);
+  while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) {
+    if (chl->channel != channel)
       continue;
 
-    client->channel[i] = NULL;
+    ch = chl->channel;
 
-    /* Remove from channel */
-    silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-      if (chl->client == client) {
-       
-       /* If this client is last one on the channel the channel
-          is removed all together. */
-       if (silc_list_count(channel->user_list) == 1) {
-         /* Notify about leaving client if this channel has global users,
-            ie. the channel is not created locally. */
-         if (notify && channel->global_users)
-           silc_server_send_notify_to_channel(server, channel,
-                                              SILC_NOTIFY_TYPE_LEAVE, 1,
-                                              clidp->data, clidp->len);
-
-         silc_idlist_del_channel(server->local_list, channel);
-         silc_buffer_free(clidp);
-         return FALSE;
-       }
-       
-       silc_list_del(channel->user_list, chl);
-       silc_free(chl);
-
-       /* Send notify to channel about client leaving the channel */
-       if (notify)
-         silc_server_send_notify_to_channel(server, channel,
-                                            SILC_NOTIFY_TYPE_LEAVE, 1,
-                                            clidp->data, clidp->len);
-      }
+    /* Remove from list */
+    silc_list_del(client->channels, chl);
+
+    /* If this client is last one on the channel the channel
+       is removed all together. */
+    if (silc_list_count(channel->user_list) < 2) {
+      /* Notify about leaving client if this channel has global users,
+        ie. the channel is not created locally. */
+      if (notify && channel->global_users)
+       silc_server_send_notify_to_channel(server, channel,
+                                          SILC_NOTIFY_TYPE_LEAVE, 1,
+                                          clidp->data, clidp->len);
+      
+      silc_idlist_del_channel(server->local_list, channel);
+      silc_buffer_free(clidp);
+      return FALSE;
     }
+
+    /* Remove from list */
+    silc_list_del(channel->user_list, chl);
+    silc_free(chl);
+
+    /* Send notify to channel about client leaving the channel */
+    if (notify)
+      silc_server_send_notify_to_channel(server, channel,
+                                        SILC_NOTIFY_TYPE_LEAVE, 1,
+                                        clidp->data, clidp->len);
+    break;
   }
 
   silc_buffer_free(clidp);
@@ -2382,15 +2376,15 @@ int silc_server_remove_from_one_channel(SilcServer server,
 int silc_server_client_on_channel(SilcClientEntry client,
                                  SilcChannelEntry channel)
 {
-  int i;
+  SilcChannelClientEntry chl;
 
   if (!client || !channel)
     return FALSE;
 
-  for (i = 0; i < client->channel_count; i++) {
-    if (client->channel[i] == channel)
+  silc_list_start(client->channels);
+  while ((chl = silc_list_get(client->channels)) != SILC_LIST_END)
+    if (chl->channel == channel)
       return TRUE;
-  }
 
   return FALSE;
 }
@@ -2552,11 +2546,9 @@ void silc_server_channel_message(SilcServer server,
 {
   SilcChannelEntry channel = NULL;
   SilcChannelClientEntry chl;
-  SilcClientEntry client = NULL;
   SilcChannelID *id = NULL;
   void *sender = NULL;
   SilcBuffer buffer = packet->buffer;
-  int i;
 
   SILC_LOG_DEBUG(("Processing channel message"));
 
@@ -2624,7 +2616,6 @@ void silc_server_channel_key(SilcServer server,
   unsigned char *tmp;
   unsigned int tmp_len;
   char *cipher;
-  int i;
 
   if (packet->src_id_type != SILC_ID_SERVER &&
       sock->type != SILC_SOCKET_TYPE_ROUTER)
@@ -2800,7 +2791,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
                                         SilcNotifyType type,
                                         unsigned int argc, ...)
 {
-  int i, j, k;
+  int k;
   SilcSocketConnection sock = NULL;
   SilcPacketContext packetdata;
   SilcClientEntry c;
@@ -2809,7 +2800,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
   SilcServerEntry *routed = NULL;
   unsigned int routed_count = 0;
   SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
+  SilcChannelClientEntry chl, chl2;
   SilcCipher cipher;
   SilcHmac hmac;
   SilcBuffer packet;
@@ -2818,7 +2809,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
   int force_send = FALSE;
   va_list ap;
 
-  if (!client->channel_count)
+  if (!silc_list_count(client->channels))
     return;
 
   va_start(ap, argc);
@@ -2834,16 +2825,14 @@ void silc_server_send_notify_on_channels(SilcServer server,
   packetdata.src_id_type = SILC_ID_SERVER;
   packetdata.rng = server->rng;
 
-  for (i = 0; i < client->channel_count; i++) {
-    channel = client->channel[i];
+  silc_list_start(client->channels);
+  while ((chl = silc_list_get(client->channels)) != SILC_LIST_END) {
+    channel = chl->channel;
 
-    if (!channel)
-      continue;
-
-    /* Send the message to clients on the channel's client list. */
+    /* Send the message to all clients on the channel's client list. */
     silc_list_start(channel->user_list);
-    while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-      c = chl->client;
+    while ((chl2 = silc_list_get(channel->user_list)) != SILC_LIST_END) {
+      c = chl2->client;
       
       /* Check if we have sent the packet to this client already */
       for (k = 0; k < sent_clients_count; k++)
@@ -3151,12 +3140,6 @@ SilcChannelEntry silc_server_new_channel(SilcServer server,
     return NULL;
   }
 
-#if 0
-  /* Add to cache */
-  silc_idcache_add(server->local_list->channels, channel_name,
-                  SILC_ID_CHANNEL, channel_id, (void *)entry, TRUE);
-#endif
-
   entry->key = silc_calloc(key_len, sizeof(*entry->key));
   entry->key_len = key_len * 8;
   memcpy(entry->key, channel_key, key_len);
index 0093ac8429a5ade3e586f515d5a872c2c40fbe9b..e0c037e8f6a7c2267f18b4900a77f8c49f00c6f4 100644 (file)
@@ -82,9 +82,8 @@ typedef struct SilcServerObjectStruct {
   SilcServerStatistics stats;
 
 #ifdef SILC_SIM
-  /* SIM (SILC Module) table */
-  SilcSimContext **sim;
-  unsigned int sim_count;
+  /* SIM (SILC Module) list */
+  SilcDList sim;
 #endif
 } SilcServerObject;
 
index fc89baced403a8e8979e93e68c18893263bab274..34985bad68c9f26444cd9a0084adde19ec183541 100644 (file)
 /*
  * $Id$
  * $Log$
+ * Revision 1.5  2000/11/02 22:15:23  priikone
+ *     Some bugfixes.
+ *     Changed server->sim to SilcDList and code accordingly.
+ *     Changes SilcClientEntry->channel to SilcList and added
+ *     back-pointer to SilcChannelClientEntry which is now used by both
+ *     client entry and channel entry
+ *
  * Revision 1.4  2000/10/06 08:10:23  priikone
  *     Added WHOIS to send multiple replies if multiple nicknames are
  *     found.
@@ -1203,12 +1210,8 @@ void silc_config_server_register_ciphers(SilcConfigServer config)
                                                SILC_CIPHER_SIM_CONTEXT_LEN));
        SILC_LOG_DEBUG(("context_len=%p", cipher.context_len));
 
-       /* Put the SIM to the table of all SIM's in server */
-       server->sim = silc_realloc(server->sim,
-                                  sizeof(*server->sim) * 
-                                  (server->sim_count + 1));
-       server->sim[server->sim_count] = sim;
-       server->sim_count++;
+       /* Put the SIM to the list of all SIM's in server */
+       silc_dlist_add(server->sim, sim);
       } else {
        SILC_LOG_ERROR(("Error configuring ciphers"));
        silc_server_stop(server);
@@ -1310,11 +1313,7 @@ void silc_config_server_register_hashfuncs(SilcConfigServer config)
        SILC_LOG_DEBUG(("context_len=%p", hash.context_len));
 
        /* Put the SIM to the table of all SIM's in server */
-       server->sim = silc_realloc(server->sim,
-                                  sizeof(*server->sim) * 
-                                  (server->sim_count + 1));
-       server->sim[server->sim_count] = sim;
-       server->sim_count++;
+       silc_dlist_add(server->sim, sim);
       } else {
        SILC_LOG_ERROR(("Error configuring hash functions"));
        silc_server_stop(server);