updates.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 19 May 2001 21:16:49 +0000 (21:16 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 19 May 2001 21:16:49 +0000 (21:16 +0000)
22 files changed:
CHANGES
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
lib/silcclient/client.c
lib/silcclient/client_channel.c
lib/silcclient/client_notify.c
lib/silcclient/client_prvmsg.c
lib/silcclient/command.c
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silccore/id.h
lib/silccore/idcache.c
lib/silccore/idcache.h
lib/silcutil/silchashtable.c
lib/silcutil/silchashtable.h
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

diff --git a/CHANGES b/CHANGES
index 0c7bd93254bab977c13b68f5b4ecfd5de1dcc745..bc2d871e5ccb196f9184552dbbb484bf025dc38f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,43 @@
+Sat May 19 16:30:03 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Removed the `data' and `data_len' arguments from the ID Cache
+         interfaces and added `name' argument.  ID Cache does not handle
+         anymore the binary data only a names associated with given ID.
+
+       * When hashing a Client ID with silc_hash_id the entire ID is
+         not hashed anymore, instead only the hash of the Client ID is
+         hashed.  This way we can access the Client ID from the cache
+         with Client ID but with the hash of the ID (which is a hash of
+         the nickname) as well without any difference in performance.
+
+         Added also silc_idcache_find_by_id_one_ext to do one on one 
+         searching when we have the actual ID.  Added also function
+         silc_hash_client_id_compare.  The affected files are
+         lib/silccore/idcache.[ch] and lib/silcutil/silcutil.[ch].
+
+       * When hashing the name associated with a ID it is always done
+         in lowercase.  This way we can access the cache without worrying
+         about case-sensitivity, even though, for example nicknames are
+         case sensitive.
+
+       * Fixed a bug in server with channel message sending.  It put
+         wrong ID type as destination ID.  The affected file 
+         silcd/packet_send.c.
+
+       * silc_idcache_del_by_context now deletes from all hash tables
+         by context.  Affected file lib/silccore/idcache.c.
+
+Fri May 18 17:42:00 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+       * Changed the client library to use the new ID Cache interface.
+         Changes around the source tree.
+
+       * Added silc_hash_table_rehash_ext to rehash with specific
+         hash function.  Affected file lib/silcutil/silchashtable.[ch].
+
+       * Added silc_hash_string_compare to compare two strings in the
+         hash table.  Affected file lib/silcutil/silcutil.[ch].
+
 Fri May 18 11:18:45 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Added new function silc_idcache_del_by_context into the
index b260c141524f0dc96c8631f6bf8e71b6dc345b32..28cd5674cea127d04a3f0928a4149c8e1d4ada30 100644 (file)
@@ -1764,7 +1764,7 @@ SILC_SERVER_CMD_FUNC(nick)
                                        new_id);
 
   /* Remove old cache entry */
-  silc_idcache_del_by_id(server->local_list->clients, client->id);
+  silc_idcache_del_by_context(server->local_list->clients, client);
 
   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
@@ -1781,8 +1781,7 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Update client cache */
   silc_idcache_add(server->local_list->clients, client->nickname, 
-                  strlen(client->nickname), client->id, 
-                  (void *)client, FALSE);
+                  client->id, (void *)client, FALSE);
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
index fa0e2be2c49f1d2a8b648e3e568abbf581412dee..7b5ef1176d88171844aa1ad47dbe794454fe6834 100644 (file)
@@ -185,7 +185,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     /* We don't have that client anywhere, add it. The client is added
        to global list since server didn't have it in the lists so it must be 
        global. */
-    client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
+    client = silc_idlist_add_client(server->global_list, nick, 
                                    strdup(username), 
                                    strdup(realname), client_id, 
                                    cmd->sock->user_data, NULL);
@@ -228,8 +228,8 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     silc_idcache_del_by_context(global ? server->global_list->clients :
                                server->local_list->clients, client);
     silc_idcache_add(global ? server->global_list->clients :
-                    server->local_list->clients, nick, strlen(nick),
-                    client->id, client, FALSE);
+                    server->local_list->clients, nick, client->id, 
+                    client, FALSE);
     silc_free(client_id);
   }
 
@@ -322,7 +322,7 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
     /* We don't have that client anywhere, add it. The client is added
        to global list since server didn't have it in the lists so it must be 
        global. */
-    client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
+    client = silc_idlist_add_client(server->global_list, nick,
                                    strdup(username), strdup(realname), 
                                    silc_id_dup(client_id, SILC_ID_CLIENT), 
                                    cmd->sock->user_data, NULL);
@@ -361,8 +361,8 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
     silc_idcache_del_by_context(global ? server->global_list->clients :
                                server->local_list->clients, client);
     silc_idcache_add(global ? server->global_list->clients :
-                    server->local_list->clients, nick, strlen(nick),
-                    client->id, client, FALSE);
+                    server->local_list->clients, nick, client->id, 
+                    client, FALSE);
   }
 
   silc_free(client_id);
@@ -449,7 +449,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
     /* We don't have that client anywhere, add it. The client is added
        to global list since server didn't have it in the lists so it must be 
        global. */
-    client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
+    client = silc_idlist_add_client(server->global_list, nick, 
                                    username ? strdup(username) : NULL, NULL,
                                    client_id, cmd->sock->user_data, NULL);
     client->data.registered = TRUE;
@@ -485,8 +485,8 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       silc_idcache_del_by_context(global ? server->global_list->clients :
                                  server->local_list->clients, client);
       silc_idcache_add(global ? server->global_list->clients :
-                      server->local_list->clients, nick, strlen(nick),
-                      client->id, client, FALSE);
+                      server->local_list->clients, nick, client->id, 
+                      client, FALSE);
     }
     silc_free(client_id);
   }
index d3d0b200f1b6b2fa6deeab90d341768cb07012cb..8da1366274fc7cfd2f0841a95c8945de835615c8 100644 (file)
@@ -112,7 +112,6 @@ silc_idlist_add_server(SilcIDList id_list,
   server->connection = connection;
 
   if (!silc_idcache_add(id_list->servers, server->server_name, 
-                       server->server_name ? strlen(server->server_name) : 0,
                        (void *)server->id, (void *)server, FALSE)) {
     silc_free(server);
     return NULL;
@@ -136,8 +135,8 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
   SILC_LOG_DEBUG(("Server ID (%s)",
                  silc_id_render(id, SILC_ID_SERVER)));
 
-  if (!silc_idcache_find_by_id(id_list->servers, (void *)id, 
-                              &id_cache))
+  if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, 
+                                  &id_cache))
     return NULL;
 
   server = (SilcServerEntry)id_cache->context;
@@ -159,8 +158,7 @@ silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
 
   SILC_LOG_DEBUG(("Server by name `%s'", name));
 
-  if (!silc_idcache_find_by_data_one(id_list->servers, name, strlen(name),
-                                    &id_cache))
+  if (!silc_idcache_find_by_name_one(id_list->servers, name, &id_cache))
     return NULL;
 
   server = (SilcServerEntry)id_cache->context;
@@ -198,8 +196,8 @@ silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
     server = (SilcServerEntry)id_cache->context;
     sock = (SilcSocketConnection)server->connection;
     
-    if (sock && ((sock->hostname && !strcmp(sock->hostname, hostname)) ||
-                (sock->ip && !strcmp(sock->ip, hostname)))
+    if (sock && ((sock->hostname && !strcasecmp(sock->hostname, hostname)) ||
+                (sock->ip && !strcasecmp(sock->ip, hostname)))
        && sock->port == port)
       break;
 
@@ -234,13 +232,18 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
 
   SILC_LOG_DEBUG(("Replacing Server ID"));
 
-  if (!silc_idcache_find_by_id(id_list->servers, (void *)old_id, &id_cache))
+  if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id, 
+                                  &id_cache))
     return NULL;
 
   server = (SilcServerEntry)id_cache->context;
   silc_free(server->id);
   server->id = new_id;
-  id_cache->id = (void *)new_id;
+
+  /* Remove the old entry and add a new one */
+  silc_idcache_del_by_context(id_list->servers, server);
+  silc_idcache_add(id_list->servers, server->server_name, server->id, 
+                  server, FALSE);
 
   SILC_LOG_DEBUG(("Found"));
 
@@ -289,8 +292,7 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
    to be directly connected local client and `router' must be NULL. */
 
 SilcClientEntry
-silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname, 
-                      uint32 nickname_len, char *username, 
+silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, 
                       char *userinfo, SilcClientID *id, 
                       SilcServerEntry router, void *connection)
 {
@@ -308,8 +310,8 @@ silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
   silc_list_init(client->channels, struct SilcChannelClientEntryStruct, 
                 client_list);
 
-  if (!silc_idcache_add(id_list->clients, nickname,  nickname_len,
-                       (void *)client->id, (void *)client, FALSE)) {
+  if (!silc_idcache_add(id_list->clients, nickname, (void *)client->id, 
+                       (void *)client, FALSE)) {
     silc_free(client);
     return NULL;
   }
@@ -327,7 +329,7 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
   if (entry) {
     /* Remove from cache */
     if (entry->id)
-      if (!silc_idcache_del_by_id(id_list->clients, (void *)entry->id))
+      if (!silc_idcache_del_by_context(id_list->clients, entry))
        return FALSE;
 
     /* Free data */
@@ -363,8 +365,7 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
 
   SILC_LOG_DEBUG(("Start"));
 
-  if (!silc_idcache_find_by_data(id_list->clients, nickname, strlen(nickname),
-                                &list))
+  if (!silc_idcache_find_by_name(id_list->clients, nickname, &list))
     return FALSE;
 
   *clients = silc_realloc(*clients, 
@@ -385,12 +386,8 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
   return TRUE;
 }
 
-/* Returns all clients matching requested nickname. Number of clients is
-   returned to `clients_count'. Caller must free the returned table. */
-/* XXX This actually checks the data, which can be hash of the nickname
-   but is not if the client is local client. Global client on global
-   list may have hash.  Thus, this is not fully reliable function.
-   Instead this should probably check the hash from the list of client ID's. */
+/* Returns all clients matching requested nickname hash. Number of clients
+   is returned to `clients_count'. Caller must free the returned table. */
 
 int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
                                    SilcHash md5hash,
@@ -401,13 +398,15 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
   SilcIDCacheEntry id_cache = NULL;
   unsigned char hash[32];
   int i;
+  SilcClientID client_id;
 
   SILC_LOG_DEBUG(("Start"));
 
   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
 
-  if (!silc_idcache_find_by_data(id_list->clients, hash, 
-                                md5hash->hash->hash_len, &list))
+  memset(&client_id, 0, sizeof(client_id));
+  memcpy(&client_id.hash, hash, sizeof(client_id.hash));
+  if (!silc_idcache_find_by_id(id_list->clients, &client_id, &list))
     return FALSE;
 
   *clients = silc_realloc(*clients, 
@@ -443,7 +442,14 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
   SILC_LOG_DEBUG(("Client ID (%s)", 
                  silc_id_render(id, SILC_ID_CLIENT)));
 
-  if (!silc_idcache_find_by_id(id_list->clients, (void *)id, &id_cache))
+  /* Do extended search since the normal ID comparison function for
+     Client ID's compares only the hash from the Client ID and not the
+     entire ID. The silc_hash_client_id_compare compares the entire
+     Client ID as we want to find one specific Client ID. */
+  if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache))
     return NULL;
 
   client = (SilcClientEntry)id_cache->context;
@@ -470,23 +476,24 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
 
   SILC_LOG_DEBUG(("Replacing Client ID"));
 
-  if (!silc_idcache_find_by_id(id_list->clients, (void *)old_id, &id_cache))
+  /* Do extended search since the normal ID comparison function for
+     Client ID's compares only the hash from the Client ID and not the
+     entire ID. The silc_hash_client_id_compare compares the entire
+     Client ID as we want to find one specific Client ID. */
+  if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)old_id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache))
     return NULL;
 
   client = (SilcClientEntry)id_cache->context;
   silc_free(client->id);
   client->id = new_id;
-  id_cache->id = (void *)new_id;
 
-  /* XXX does not work correctly with the new ID Cache */
-
-  /* If the old ID Cache data was the hash value of the old Client ID
-     replace it with the hash of new Client ID */
-  if (id_cache->data && SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
-    silc_free(id_cache->data);
-    id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
-    memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
-  }
+  /* Remove the old entry and add a new one */
+  silc_idcache_del_by_context(id_list->clients, client);
+  silc_idcache_add(id_list->clients, client->nickname, client->id, 
+                  client, FALSE);
 
   SILC_LOG_DEBUG(("Replaced"));
 
@@ -551,7 +558,6 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
                 channel_list);
 
   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
-                       strlen(channel->channel_name),
                        (void *)channel->id, (void *)channel, FALSE)) {
     silc_free(channel);
     return NULL;
@@ -618,30 +624,19 @@ SilcChannelEntry
 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
                                 SilcIDCacheEntry *ret_entry)
 {
-  SilcIDCacheList list = NULL;
   SilcIDCacheEntry id_cache = NULL;
-  SilcChannelEntry channel;
 
   SILC_LOG_DEBUG(("Channel by name"));
 
-  if (!silc_idcache_find_by_data(id_list->channels, name, strlen(name), &list))
-    return NULL;
-  
-  if (!silc_idcache_list_first(list, &id_cache)) {
-    silc_idcache_list_free(list);
+  if (!silc_idcache_find_by_name_one(id_list->channels, name, &id_cache))
     return NULL;
-  }
-
-  channel = (SilcChannelEntry)id_cache->context;
 
   if (ret_entry)
     *ret_entry = id_cache;
 
-  silc_idcache_list_free(list);
-
   SILC_LOG_DEBUG(("Found"));
 
-  return channel;
+  return id_cache->context;
 }
 
 /* Finds channel by Channel ID. */
@@ -659,7 +654,7 @@ silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
   SILC_LOG_DEBUG(("Channel ID (%s)",
                  silc_id_render(id, SILC_ID_CHANNEL)));
 
-  if (!silc_idcache_find_by_id(id_list->channels, (void *)id, &id_cache))
+  if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id, &id_cache))
     return NULL;
 
   channel = (SilcChannelEntry)id_cache->context;
@@ -687,13 +682,18 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
 
   SILC_LOG_DEBUG(("Replacing Channel ID"));
 
-  if (!silc_idcache_find_by_id(id_list->channels, (void *)old_id, &id_cache))
+  if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id, 
+                                  &id_cache))
     return NULL;
 
   channel = (SilcChannelEntry)id_cache->context;
   silc_free(channel->id);
   channel->id = new_id;
-  id_cache->id = (void *)new_id;
+
+  /* Remove the old entry and add a new one */
+  silc_idcache_del_by_context(id_list->channels, channel);
+  silc_idcache_add(id_list->channels, channel->channel_name, channel->id, 
+                  channel, FALSE);
 
   SILC_LOG_DEBUG(("Replaced"));
 
@@ -729,7 +729,7 @@ silc_idlist_get_channels(SilcIDList id_list, SilcChannelID *channel_id,
     
     silc_idcache_list_free(list);
   } else {
-    if (!silc_idcache_find_by_id(id_list->channels, channel_id, &id_cache))
+    if (!silc_idcache_find_by_id_one(id_list->channels, channel_id, &id_cache))
       return NULL;
 
     i = 1;
index 38181263433966284758ea8db622b83a6748529f..e070b1ca815e91273ead1757ed5ddf59b1886313 100644 (file)
@@ -545,8 +545,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
                              SilcServerID *new_id);
 int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
 SilcClientEntry
-silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname, 
-                      uint32 nickname_len, char *username, 
+silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username, 
                       char *userinfo, SilcClientID *id, 
                       SilcServerEntry router, void *connection);
 int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
index 5091da02e7ffe22e41771340e58954e5323ba4aa..1b3303b48caff2f86787c60bde4d19c252977902 100644 (file)
@@ -150,7 +150,7 @@ void silc_server_notify(SilcServer server,
          goto out;
 
        client = 
-         silc_idlist_add_client(server->global_list, NULL, 0, NULL, NULL,
+         silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
                                 silc_id_dup(client_id, SILC_ID_CLIENT), 
                                 sock->user_data, NULL);
        if (!client) {
@@ -1291,7 +1291,12 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   idata = (SilcIDListData)client;
 
   /* Remove the old cache entry */
-  silc_idcache_del_by_context(server->local_list->clients, client);
+  if (!silc_idcache_del_by_context(server->local_list->clients, client)) {
+    SILC_LOG_ERROR(("Lost client's cache entry - bad thing"));
+    silc_server_disconnect_remote(server, sock, "Server closed connection: "
+                                  "Unknown client");
+    return NULL;
+  }
 
   /* Parse incoming packet */
   ret = silc_buffer_unformat(buffer,
@@ -1334,7 +1339,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
 
   /* Add the client again to the ID cache */
   silc_idcache_add(server->local_list->clients, client->nickname,
-                  strlen(client->nickname), client_id, client, FALSE);
+                  client_id, client, FALSE);
 
   /* Notify our router about new client on the SILC network */
   if (!server->standalone)
@@ -1481,8 +1486,8 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   new_server->id = server_id;
 
   /* Add again the entry to the ID cache. */
-  silc_idcache_add(server->local_list->servers, server_name, 
-                  strlen(server_name), server_id, server, FALSE);
+  silc_idcache_add(server->local_list->servers, server_name, server_id, 
+                  server, FALSE);
 
   /* Distribute the information about new server in the SILC network
      to our router. If we are normal server we won't send anything
@@ -1513,7 +1518,6 @@ static void silc_server_new_id_real(SilcServer server,
   SilcSocketConnection router_sock;
   SilcIDPayload idp;
   SilcIdType id_type;
-  unsigned char *hash = NULL;
   void *id;
 
   SILC_LOG_DEBUG(("Processing new ID"));
@@ -1586,16 +1590,9 @@ static void silc_server_new_id_real(SilcServer server,
     
       /* As a router we keep information of all global information in our
         global list. Cell wide information however is kept in the local
-        list. The client is put to global list and we will take the hash
-        value of the Client ID and save it to the ID Cache system for fast
-        searching in the future. */
-      hash = silc_calloc(sizeof(((SilcClientID *)id)->hash),
-                        sizeof(unsigned char));
-      memcpy(hash, ((SilcClientID *)id)->hash, 
-            sizeof(((SilcClientID *)id)->hash));
-      entry = silc_idlist_add_client(id_list, hash, 
-                                    sizeof(((SilcClientID *)id)->hash),
-                                    NULL, NULL, id, router, NULL);
+        list. */
+      entry = silc_idlist_add_client(id_list, NULL, NULL, NULL, 
+                                    id, router, NULL);
       entry->nickname = NULL;
       entry->data.registered = TRUE;
 
index dc0d84a1905b919268e4cad24a88d9bb9aa5e9db..c4d33dd80600abc727cce36e44d35e41fc33dc09 100644 (file)
@@ -434,8 +434,8 @@ void silc_server_packet_send_to_channel(SilcServer server,
   packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
   packetdata.src_id_type = SILC_ID_SERVER;
   packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
-  packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
-  packetdata.dst_id_type = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+  packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+  packetdata.dst_id_type = SILC_ID_CHANNEL;
   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
     packetdata.src_id_len + packetdata.dst_id_len;
   packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
@@ -614,8 +614,8 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   packetdata.src_id_len = silc_id_get_len(sender, sender_type);
   packetdata.src_id_type = sender_type;
   packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
-  packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
-  packetdata.dst_id_type = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+  packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+  packetdata.dst_id_type = SILC_ID_CHANNEL;
   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
                                          packetdata.src_id_len +
                                          packetdata.dst_id_len));
index 8435e02af0269060911d6159e8ac0d1981ac86ad..2eae57b86ec79e5f2f69a727d01b4df8e75fc7d9 100644 (file)
@@ -1244,7 +1244,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
         and other information is created after we have received NEW_CLIENT
         packet from client. */
       client = silc_idlist_add_client(server->local_list, 
-                                     NULL, 0, NULL, NULL, NULL, NULL, sock);
+                                     NULL, NULL, NULL, NULL, NULL, sock);
       if (!client) {
        SILC_LOG_ERROR(("Could not add new client to cache"));
        silc_free(sock->user_data);
@@ -3542,8 +3542,7 @@ void silc_server_save_users_on_channel(SilcServer server,
       /* We don't have that client anywhere, add it. The client is added
         to global list since server didn't have it in the lists so it must be 
         global. */
-      client = silc_idlist_add_client(server->global_list, NULL, 0, NULL, 
-                                     NULL, 
+      client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
                                      silc_id_dup(client_id, SILC_ID_CLIENT), 
                                      sock->user_data, NULL);
       if (!client) {
index 1609cbe118ad53c679d0216f548cba2116f925c2..89aa1c0f4b8e057eeb8d91e56b5b4ac00ded5430 100644 (file)
@@ -142,9 +142,9 @@ SilcClientConnection silc_client_add_connection(SilcClient client,
   conn = silc_calloc(1, sizeof(*conn));
 
   /* Initialize ID caches */
-  conn->client_cache = silc_idcache_alloc(0, NULL);
-  conn->channel_cache = silc_idcache_alloc(0, NULL);
-  conn->server_cache = silc_idcache_alloc(0, NULL);
+  conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
+  conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
+  conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
   conn->client = client;
   conn->remote_host = strdup(hostname);
   conn->remote_port = port;
@@ -1374,11 +1374,13 @@ void silc_client_receive_new_id(SilcClient client,
     connecting = TRUE;
 
   /* Delete old ID from ID cache */
-  silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
+  if (conn->local_id) {
+    silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
+    silc_free(conn->local_id);
+  }
   
   /* Save the new ID */
-  if (conn->local_id)
-    silc_free(conn->local_id);
+
   if (conn->local_id_data)
     silc_free(conn->local_id_data);
 
@@ -1401,9 +1403,8 @@ void silc_client_receive_new_id(SilcClient client,
   conn->local_entry->id = conn->local_id;
   
   /* Put it to the ID cache */
-  silc_idcache_add(conn->client_cache, conn->nickname, strlen(conn->nickname),
-                  SILC_ID_CLIENT, conn->local_id, (void *)conn->local_entry,
-                  TRUE, FALSE);
+  silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, 
+                  (void *)conn->local_entry, FALSE);
 
   /* Notify application of successful connection. We do it here now that
      we've received the Client ID and are allowed to send traffic. */
@@ -1435,9 +1436,8 @@ SilcChannelEntry silc_client_new_channel_id(SilcClient client,
   conn->current_channel = channel;
 
   /* Put it to the ID cache */
-  silc_idcache_add(conn->channel_cache, channel_name, strlen(channel_name),
-                  SILC_ID_CHANNEL, (void *)channel->id, (void *)channel, 
-                  TRUE, FALSE);
+  silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id, 
+                  (void *)channel, FALSE);
 
   return channel;
 }
@@ -1455,8 +1455,7 @@ void silc_client_remove_from_channels(SilcClient client,
   SilcChannelEntry channel;
   SilcChannelUser chu;
 
-  if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
-                              SILC_ID_CHANNEL, &list))
+  if (!silc_idcache_get_all(conn->channel_cache, &list))
     return;
 
   silc_idcache_list_first(list, &id_cache);
@@ -1498,8 +1497,7 @@ void silc_client_replace_from_channels(SilcClient client,
   SilcChannelEntry channel;
   SilcChannelUser chu;
 
-  if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
-                              SILC_ID_CHANNEL, &list))
+  if (!silc_idcache_get_all(conn->channel_cache, &list))
     return;
 
   silc_idcache_list_first(list, &id_cache);
index f3dff85b6bd5a9d2f2d5b195d195b8500eb47d1d..fb23a10c33f8157e4523196b2df5488702575360 100644 (file)
@@ -185,8 +185,7 @@ void silc_client_channel_message(SilcClient client,
     goto out;
 
   /* Find the channel entry from channels on this connection */
-  if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
-                                  SILC_ID_CHANNEL, &id_cache))
+  if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id, &id_cache))
     goto out;
 
   channel = (SilcChannelEntry)id_cache->context;
@@ -275,8 +274,8 @@ void silc_client_save_channel_key(SilcClientConnection conn,
 
   /* Find channel. */
   if (!channel) {
-    if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
-                                    SILC_ID_CHANNEL, &id_cache))
+    if (!silc_idcache_find_by_id_one(conn->channel_cache, 
+                                    (void *)id, &id_cache))
       goto out;
     
     /* Get channel entry */
index 109fb0a7b1e64298afe08380e6d4e07accfe193b..ce8204e2b6065f8beff0ef2837de7bec64b35706 100644 (file)
@@ -121,7 +121,7 @@ void silc_client_notify_by_server(SilcClient client,
     /* Get the channel entry */
     channel = NULL;
     if (silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                               &id_cache))
       channel = (SilcChannelEntry)id_cache->context;
 
     /* Get sender Client ID */
@@ -188,7 +188,7 @@ void silc_client_notify_by_server(SilcClient client,
 
     /* Get channel entry */
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -236,7 +236,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!channel_id)
       goto out;
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -281,8 +281,7 @@ void silc_client_notify_by_server(SilcClient client,
     silc_client_remove_from_channels(client, conn, client_entry);
 
     /* Remove from cache */
-    silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
-                          client_entry->id);
+    silc_idcache_del_by_context(conn->client_cache, client_entry);
 
     /* Get signoff message */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
@@ -336,7 +335,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!channel_id)
       goto out;
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -391,8 +390,7 @@ void silc_client_notify_by_server(SilcClient client,
     }
 
     /* Remove the old from cache */
-    silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
-                          client_entry->id);
+    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,
@@ -461,7 +459,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!channel_id)
       goto out;
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -542,7 +540,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!channel_id)
       goto out;
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -593,7 +591,7 @@ void silc_client_notify_by_server(SilcClient client,
     
     /* Get the channel entry */
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -640,7 +638,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (!channel_id)
       goto out;
     if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                    SILC_ID_CHANNEL, &id_cache))
+                                &id_cache))
       break;
 
     channel = (SilcChannelEntry)id_cache->context;
@@ -657,8 +655,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (client_entry == conn->local_entry) {
       if (conn->current_channel == channel)
        conn->current_channel = NULL;
-      silc_idcache_del_by_id(conn->channel_cache, 
-                            SILC_ID_CHANNEL, channel->id);
+      silc_idcache_del_by_id(conn->channel_cache, channel->id);
       silc_free(channel->channel_name);
       silc_free(channel->id);
       silc_free(channel->key);
@@ -695,8 +692,7 @@ void silc_client_notify_by_server(SilcClient client,
     if (client_entry != conn->local_entry) {
       /* Remove client from all channels */
       silc_client_remove_from_channels(client, conn, client_entry);
-      silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
-                            client_entry->id);
+      silc_idcache_del_by_context(conn->client_cache, client_entry);
       if (client_entry->nickname)
        silc_free(client_entry->nickname);
       if (client_entry->server)
@@ -755,8 +751,7 @@ void silc_client_notify_by_server(SilcClient client,
          continue;
 
        silc_client_remove_from_channels(client, conn, client_entry);
-       silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, 
-                              client_entry->id);
+       silc_idcache_del_by_context(conn->client_cache, client_entry);
        if (client_entry->nickname)
          silc_free(client_entry->nickname);
        if (client_entry->server)
index 2df8325de8ec5e46c3c53587c48222ed0a780e97..53596f81cd73022601c6b047fa3f6d0959aa35aa 100644 (file)
@@ -152,8 +152,10 @@ void silc_client_private_message(SilcClient client,
     goto out;
 
   /* Check whether we know this client already */
-  if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
-                                  SILC_ID_CLIENT, &id_cache)) {
+  if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)remote_id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache)) {
     /* Resolve the client info */
     silc_client_get_client_by_id_resolve(client, conn, remote_id,
                                         silc_client_private_message_cb,
@@ -483,8 +485,7 @@ silc_client_list_private_message_keys(SilcClient client,
   SilcIDCacheList list;
   SilcClientEntry entry;
 
-  if (!silc_idcache_find_by_id(conn->client_cache, SILC_ID_CACHE_ANY, 
-                              SILC_ID_CLIENT, &list))
+  if (!silc_idcache_get_all(conn->client_cache, &list))
     return NULL;
 
   if (!silc_idcache_list_count(list)) {
index 0ad1e136aa4322ee5ef97ebc5cab813af65d7ecb..607ff9fc8151b8ad01a5e38efe8ee3b9a795582a 100644 (file)
@@ -428,7 +428,7 @@ SILC_CLIENT_CMD_FUNC(list)
     name = cmd->argv[1];
 
     /* Get the Channel ID of the channel */
-    if (silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+    if (silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
       channel = (SilcChannelEntry)id_cache->context;
       idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
     }
@@ -498,7 +498,7 @@ SILC_CLIENT_CMD_FUNC(topic)
   }
 
   /* Get the Channel ID of the channel */
-  if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+  if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
     cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
     COMMAND_ERROR;
     goto out;
@@ -928,7 +928,7 @@ SILC_CLIENT_CMD_FUNC(join)
   }
 
   /* See if we have joined to the requested channel already */
-  if (silc_idcache_find_by_data_one(conn->channel_cache, cmd->argv[1],
+  if (silc_idcache_find_by_name_one(conn->channel_cache, cmd->argv[1],
                                    &id_cache)) {
     cmd->client->ops->say(cmd->client, conn, 
                          "You are talking to channel %s", cmd->argv[1]);
@@ -1520,7 +1520,7 @@ SILC_CLIENT_CMD_FUNC(kick)
   }
 
   /* Get the Channel ID of the channel */
-  if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+  if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
     cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
     COMMAND_ERROR;
     goto out;
@@ -1934,7 +1934,7 @@ SILC_CLIENT_CMD_FUNC(leave)
   }
 
   /* Get the Channel ID of the channel */
-  if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+  if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
     cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
     COMMAND_ERROR;
     goto out;
@@ -1956,7 +1956,7 @@ SILC_CLIENT_CMD_FUNC(leave)
 
   conn->current_channel = NULL;
 
-  silc_idcache_del_by_id(conn->channel_cache, SILC_ID_CHANNEL, channel->id);
+  silc_idcache_del_by_id(conn->channel_cache, channel->id);
   silc_free(channel->channel_name);
   silc_free(channel->id);
   silc_free(channel->key);
@@ -2012,7 +2012,7 @@ SILC_CLIENT_CMD_FUNC(users)
   }
 
   /* Get the Channel ID of the channel */
-  if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+  if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
     /* XXX should resolve the channel ID; LIST command */
     cmd->client->ops->say(cmd->client, conn, 
                          "You are not on that channel", name);
index 8029eefbc1de77c12e62e81f3a34616cecd6d54b..629acd05dd31be2a0e32eb96e877e5f9b5d16926 100644 (file)
@@ -252,8 +252,10 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     SILC_GET32_MSB(idle, tmp);
 
   /* Check if we have this client cached already. */
-  if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                  SILC_ID_CLIENT, &id_cache)) {
+  if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache)) {
     SILC_LOG_DEBUG(("Adding new client entry"));
 
     client_entry = silc_calloc(1, sizeof(*client_entry));
@@ -267,9 +269,7 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     
     /* Add client to cache */
     silc_idcache_add(conn->client_cache, client_entry->nickname,
-                    strlen(client_entry->nickname),
-                    SILC_ID_CLIENT, client_id, (void *)client_entry, 
-                    TRUE, FALSE);
+                    client_id, (void *)client_entry, FALSE);
   } else {
     client_entry = (SilcClientEntry)id_cache->context;
     if (client_entry->nickname)
@@ -290,10 +290,10 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     if (realname)
       client_entry->realname = strdup(realname);
 
-    id_cache->data = client_entry->nickname;
-    id_cache->data_len = strlen(client_entry->nickname);
-    silc_idcache_sort_by_data(conn->client_cache);
-
+    /* Remove the old cache entry and create a new one */
+    silc_idcache_del_by_context(conn->client_cache, client_entry);
+    silc_idcache_add(conn->client_cache, client_entry->nickname, 
+                    client_entry->id, client_entry, FALSE);
     silc_free(client_id);
   }
 
@@ -392,8 +392,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(whowas)
   }
 
   /* Get the client entry, if exists */
-  if (silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                 SILC_ID_CLIENT, &id_cache))
+  if (silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                     NULL, NULL, 
+                                     silc_hash_client_id_compare, NULL,
+                                     &id_cache)) 
     client_entry = (SilcClientEntry)id_cache->context;
   silc_free(client_id);
 
@@ -455,8 +457,10 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
   username = silc_argument_get_arg_type(cmd->args, 4, &len);
 
   /* Check if we have this client cached already. */
-  if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                  SILC_ID_CLIENT, &id_cache)) {
+  if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache)) {
     SILC_LOG_DEBUG(("Adding new client entry"));
 
     client_entry = silc_calloc(1, sizeof(*client_entry));
@@ -468,9 +472,7 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
     
     /* Add client to cache */
     silc_idcache_add(conn->client_cache, client_entry->nickname,
-                    strlen(client_entry->nickname),
-                    SILC_ID_CLIENT, client_id, (void *)client_entry, 
-                    TRUE, FALSE);
+                    client_id, (void *)client_entry, FALSE);
   } else {
     client_entry = (SilcClientEntry)id_cache->context;
     if (client_entry->nickname)
@@ -488,10 +490,10 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
     if (username)
       client_entry->username = strdup(username);
     
-    id_cache->data = client_entry->nickname;
-    id_cache->data_len = strlen(client_entry->nickname);
-    silc_idcache_sort_by_data(conn->client_cache);
-    
+    /* Remove the old cache entry and create a new one */
+    silc_idcache_del_by_context(conn->client_cache, client_entry);
+    silc_idcache_add(conn->client_cache, client_entry->nickname, 
+                    client_entry->id, client_entry, FALSE);
     silc_free(client_id);
   }
 
@@ -685,7 +687,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
 
   /* Get the channel entry */
   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                  SILC_ID_CHANNEL, &id_cache)) {
+                                  &id_cache)) {
     silc_free(channel_id);
     COMMAND_REPLY_ERROR;
     goto out;
@@ -743,7 +745,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(invite)
 
   /* Get the channel entry */
   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                  SILC_ID_CHANNEL, &id_cache)) {
+                                  &id_cache)) {
     silc_free(channel_id);
     COMMAND_REPLY_ERROR;
     goto out;
@@ -1041,13 +1043,15 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
     SILC_GET32_MSB(mode, client_mode_list->data);
 
     /* Check if we have this client cached already. */
-    if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                    SILC_ID_CLIENT, &id_cache)) {
+    if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                        NULL, NULL, 
+                                        silc_hash_client_id_compare, NULL,
+                                        &id_cache)) {
       /* No, we don't have it, add entry for it. */
       client_entry = silc_calloc(1, sizeof(*client_entry));
       client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
-      silc_idcache_add(conn->client_cache, NULL, 0, SILC_ID_CLIENT
-                      client_entry->id, (void *)client_entry, FALSE, FALSE);
+      silc_idcache_add(conn->client_cache, NULL, client_entry->id
+                      (void *)client_entry, FALSE);
     } else {
       /* Yes, we have it already */
       client_entry = (SilcClientEntry)id_cache->context;
@@ -1272,8 +1276,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(cumode)
   }
   
   /* Get client entry */
-  if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                  SILC_ID_CLIENT, &id_cache)) {
+  if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache)) {
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1429,7 +1435,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
 
   /* Get the channel entry */
   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                  SILC_ID_CHANNEL, &id_cache)) {
+                                  &id_cache)) {
     silc_free(channel_id);
     COMMAND_REPLY_ERROR;
     goto out;
@@ -1599,7 +1605,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
 
   /* Get channel entry */
   if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                   SILC_ID_CHANNEL, &id_cache)) {
+                                  &id_cache)) {
     COMMAND_REPLY_ERROR;
     goto out;
   }
@@ -1632,8 +1638,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
     SILC_GET32_MSB(mode, client_mode_list->data);
 
     /* Check if we have this client cached already. */
-    if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                    SILC_ID_CLIENT, &id_cache)) {
+    if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                        NULL, NULL, 
+                                        silc_hash_client_id_compare, NULL,
+                                        &id_cache)) {
       /* No we don't have it, query it from the server. Assemble argument
         table that will be sent fr the IDENTIFY command later. */
       res_argv = silc_realloc(res_argv, sizeof(*res_argv) *
@@ -1765,8 +1773,10 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   if (id_type == SILC_ID_CLIENT) {
     client_id = silc_id_payload_get_id(idp);
 
-    if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                                    SILC_ID_CLIENT, &id_cache))
+    if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                        NULL, NULL, 
+                                        silc_hash_client_id_compare, NULL,
+                                        &id_cache))
       goto out;
 
     client_entry = (SilcClientEntry)id_cache->context;
index f18f073069dfecfe41acd52ac476e95f2a613e79..487b739c55b5e426bff79d328cb6aa3da5611b0e 100644 (file)
@@ -124,7 +124,8 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client,
   int i = 0;
 
   /* Find ID from cache */
-  if (!silc_idcache_find_by_data_loose(conn->client_cache, nickname, &list))
+  if (!silc_idcache_find_by_name(conn->client_cache, nickname, 
+                                &list))
     return NULL;
 
   if (!silc_idcache_list_count(list)) {
@@ -201,8 +202,11 @@ SILC_CLIENT_CMD_FUNC(get_clients_list_callback)
       continue;
 
     /* Get the client entry */
-    if (silc_idcache_find_by_id_one(i->conn->client_cache, (void *)client_id,
-                                   SILC_ID_CLIENT, &id_cache)) {
+    if (silc_idcache_find_by_id_one_ext(i->conn->client_cache, 
+                                       (void *)client_id, 
+                                       NULL, NULL, 
+                                       silc_hash_client_id_compare, NULL,
+                                       &id_cache)) {
       clients = silc_realloc(clients, sizeof(*clients) * 
                             (clients_count + 1));
       clients[clients_count] = (SilcClientEntry)id_cache->context;
@@ -274,8 +278,10 @@ void silc_client_get_clients_by_list(SilcClient client,
 
     /* Check if we have this client cached already. */
     id_cache = NULL;
-    silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
-                               SILC_ID_CLIENT, &id_cache);
+    silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                   NULL, NULL, 
+                                   silc_hash_client_id_compare, NULL,
+                                   &id_cache);
 
     /* If we don't have the entry or it has incomplete info, then resolve
        it from the server. */
@@ -351,7 +357,8 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
   SilcClientEntry entry = NULL;
 
   /* Find ID from cache */
-  if (!silc_idcache_find_by_data_loose(conn->client_cache, nickname, &list)) {
+  if (!silc_idcache_find_by_name(conn->client_cache, nickname, 
+                                &list)) {
   identify:
 
     if (query) {
@@ -431,8 +438,10 @@ SilcClientEntry silc_client_get_client_by_id(SilcClient client,
                  silc_id_render(client_id, SILC_ID_CLIENT)));
 
   /* Find ID from cache */
-  if (!silc_idcache_find_by_id_one(conn->client_cache, client_id, 
-                                  SILC_ID_CLIENT, &id_cache))
+  if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id, 
+                                      NULL, NULL, 
+                                      silc_hash_client_id_compare, NULL,
+                                      &id_cache))
     return NULL;
 
   SILC_LOG_DEBUG(("Found"));
@@ -519,7 +528,8 @@ SilcChannelEntry silc_client_get_channel(SilcClient client,
   SilcIDCacheEntry id_cache;
   SilcChannelEntry entry;
 
-  if (!silc_idcache_find_by_data_one(conn->channel_cache, channel, &id_cache))
+  if (!silc_idcache_find_by_name_one(conn->channel_cache, channel, 
+                                    &id_cache))
     return NULL;
 
   entry = (SilcChannelEntry)id_cache->context;
index 349f65150eafb928259026c07b73ba90c57ffda3..114583bbce62de8919481488e491915bd5800154 100644 (file)
@@ -119,8 +119,8 @@ typedef struct {
    SILC_ID_CHANNEL_COMPARE(id1, id2))
 
 /* Compare nickname hash from Client ID */
-#define SILC_ID_COMPARE_HASH(id, _hash) \
-  memcmp(id->hash, _hash, CLIENTID_HASH_LEN)
+#define SILC_ID_COMPARE_HASH(id1, id2) \
+  (!memcmp((id1)->hash, (id2)->hash, CLIENTID_HASH_LEN))
 
 /* Prototypes */
 unsigned char *silc_id_id2str(void *id, SilcIdType type);
index 7e6aa02b7d02881a026e3e7e045e7a799425d184..ee557dce87a8c5be33a9c3838d008b3294553735 100644 (file)
@@ -42,9 +42,9 @@ static void silc_idcache_list_add(SilcIDCacheList list,
 
        Hash table using the ID as the key.
 
-   SilcHashTable data_table
+   SilcHashTable name_table
 
-       Hash table using the data as the key.
+       Hash table using the name as the key.
 
    SilcHashTable context_table
 
@@ -64,7 +64,7 @@ static void silc_idcache_list_add(SilcIDCacheList list,
 */
 struct SilcIDCacheStruct {
   SilcHashTable id_table;
-  SilcHashTable data_table;
+  SilcHashTable name_table;
   SilcHashTable context_table;
   SilcIDCacheDestructor destructor;
   SilcIdType type;
@@ -110,8 +110,8 @@ SilcIDCache silc_idcache_alloc(uint32 count, SilcIdType id_type,
                                          silc_hash_id_compare, 
                                          (void *)(uint32)id_type, 
                                          silc_idcache_destructor, NULL);
-  cache->data_table = silc_hash_table_alloc(count, silc_hash_data, NULL,
-                                           silc_hash_data_compare, NULL, 
+  cache->name_table = silc_hash_table_alloc(count, silc_hash_string, NULL,
+                                           silc_hash_string_compare, NULL, 
                                            NULL, NULL);
   cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL,
                                               NULL, NULL, NULL, NULL);
@@ -127,7 +127,7 @@ void silc_idcache_free(SilcIDCache cache)
 {
   if (cache) {
     silc_hash_table_free(cache->id_table);
-    silc_hash_table_free(cache->data_table);
+    silc_hash_table_free(cache->name_table);
     silc_hash_table_free(cache->context_table);
     silc_free(cache);
   }
@@ -135,32 +135,27 @@ void silc_idcache_free(SilcIDCache cache)
 
 /* Add new entry to the cache. */
 
-bool silc_idcache_add(SilcIDCache cache, unsigned char *data
-                     uint32 data_len, void *id, void *context, int expire)
+bool silc_idcache_add(SilcIDCache cache, char *name, void *id
+                     void *context, int expire)
 {
   SilcIDCacheEntry c;
   uint32 curtime = time(NULL);
 
   SILC_LOG_DEBUG(("Adding cache entry"));
 
-  /* See if entry with this ID already exists. */
-  if (silc_hash_table_find(cache->id_table, id, NULL, NULL))
-    return FALSE;
-
   /* Allocate new cache entry */
   c = silc_calloc(1, sizeof(*c));
-  c->data = data;
-  c->data_len = data_len;
   c->id = id;
+  c->name = name;
   c->expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
   c->context = context;
 
   /* Add the new entry to the hash tables */
 
-  silc_hash_table_add(cache->id_table, id, c);
-  if (data)
-    silc_hash_table_add_ext(cache->data_table, data, c,
-                           silc_hash_data, (void *)data_len);
+  if (id)
+    silc_hash_table_add(cache->id_table, id, c);
+  if (name)
+    silc_hash_table_add(cache->name_table, name, c);
   if (context)
     silc_hash_table_add(cache->context_table, context, c);
 
@@ -168,7 +163,7 @@ bool silc_idcache_add(SilcIDCache cache, unsigned char *data,
   if ((silc_hash_table_count(cache->id_table) / 2) >
       silc_hash_table_size(cache->id_table)) {
     silc_hash_table_rehash(cache->id_table, 0);
-    silc_hash_table_rehash(cache->data_table, 0);
+    silc_hash_table_rehash(cache->name_table, 0);
     silc_hash_table_rehash(cache->context_table, 0);
   }
 
@@ -187,15 +182,16 @@ static void silc_idcache_destructor(void *key, void *context,
 
 bool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old)
 {
-  bool ret;
+  bool ret = FALSE;
+
+  SILC_LOG_DEBUG(("Deleting cache entry"));
 
-  ret = silc_hash_table_del_by_context_ext(cache->data_table, old->data, old,
-                                          silc_hash_data, 
-                                          (void *)old->data_len,
-                                          silc_hash_data_compare,
-                                          (void *)old->data_len);
-  ret = silc_hash_table_del(cache->context_table, old->context);
-  ret = silc_hash_table_del(cache->id_table, old->id);
+  if (old->name)
+    ret = silc_hash_table_del_by_context(cache->name_table, old->name, old);
+  if (old->context)
+    ret = silc_hash_table_del(cache->context_table, old->context);
+  if (old->id)
+    ret = silc_hash_table_del(cache->id_table, old->id);
 
   return ret;
 }
@@ -212,16 +208,56 @@ bool silc_idcache_del_by_id(SilcIDCache cache, void *id)
   return silc_idcache_del(cache, c);
 }
 
+/* Same as above but with specific hash and comparison functions. If the
+   functions are NULL then default values are used. */
+
+bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
+                               SilcHashFunction hash, 
+                               void *hash_context,
+                               SilcHashCompare compare, 
+                               void *compare_context)
+{
+  SilcIDCacheEntry c;
+  bool ret = FALSE;
+
+  SILC_LOG_DEBUG(("Deleting cache entry"));
+
+  if (!silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)&c,
+                               hash, hash_context, compare, 
+                               compare_context))
+    return FALSE;
+
+  if (c->name)
+    ret = silc_hash_table_del_by_context(cache->name_table, c->name, c);
+  if (c->context)
+    ret = silc_hash_table_del(cache->context_table, c->context);
+  if (c->id)
+    ret = silc_hash_table_del_ext(cache->id_table, c->id, hash,
+                                 hash_context, compare, compare_context);
+
+  return ret;
+}
+
 /* Deletes ID cache entry by context. */
 
 bool silc_idcache_del_by_context(SilcIDCache cache, void *context)
 {
   SilcIDCacheEntry c;
+  bool ret = FALSE;
+
+  SILC_LOG_DEBUG(("Deleting cache entry"));
 
   if (!silc_hash_table_find(cache->context_table, context, NULL, (void *)&c))
     return FALSE;
 
-  return silc_idcache_del(cache, c);
+  if (c->name)
+    ret = silc_hash_table_del_by_context(cache->name_table, c->name, c);
+  if (c->context)
+    ret = silc_hash_table_del(cache->context_table, c->context);
+  if (c->id)
+    ret = silc_hash_table_del_by_context(cache->id_table, c->id, c);
+
+  return ret;
 }
 
 /* Deletes all ID entries from cache. Free's memory as well. */
@@ -229,7 +265,7 @@ bool silc_idcache_del_by_context(SilcIDCache cache, void *context)
 bool silc_idcache_del_all(SilcIDCache cache)
 {
   silc_hash_table_free(cache->id_table);
-  silc_hash_table_free(cache->data_table);
+  silc_hash_table_free(cache->name_table);
   silc_hash_table_free(cache->context_table);
 
   return TRUE;
@@ -312,10 +348,51 @@ bool silc_idcache_get_all(SilcIDCache cache, SilcIDCacheList *ret)
   return TRUE;
 }
 
-/* Find ID Cache entry by ID. */
+/* Find ID Cache entry by ID. May return multiple entries. */
 
 bool silc_idcache_find_by_id(SilcIDCache cache, void *id, 
-                            SilcIDCacheEntry *ret)
+                            SilcIDCacheList *ret)
+{
+  SilcIDCacheList list;
+
+  list = silc_idcache_list_alloc();
+
+  if (!ret)
+    return TRUE;
+
+  silc_hash_table_find_foreach(cache->id_table, id,
+                              silc_idcache_get_all_foreach, list);
+
+  if (silc_idcache_list_count(list) == 0) {
+    silc_idcache_list_free(list);
+    return FALSE;
+  }
+
+  *ret = list;
+
+  return TRUE;
+}
+
+/* Find specific ID with specific hash function and comparison functions.
+   If `hash' is NULL then the default hash funtion is used and if `compare'
+   is NULL default comparison function is used. */
+
+bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id, 
+                                    SilcHashFunction hash, 
+                                    void *hash_context,
+                                    SilcHashCompare compare, 
+                                    void *compare_context,
+                                    SilcIDCacheEntry *ret)
+{
+  return silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)ret,
+                                 hash, hash_context, compare, 
+                                 compare_context);
+}
+
+/* Find one specific ID entry. */
+
+bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, 
+                                SilcIDCacheEntry *ret)
 {
   return silc_hash_table_find(cache->id_table, id, NULL, (void *)ret);
 }
@@ -329,11 +406,10 @@ bool silc_idcache_find_by_context(SilcIDCache cache, void *context,
                              (void *)ret);
 }
 
-/* Find ID Cache entry by data. The data maybe anything that must
-   match exactly. Returns list of cache entries. */
+/* Find ID Cache entry by name. Returns list of cache entries. */
 
-bool silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data, 
-                              unsigned int data_len, SilcIDCacheList *ret)
+bool silc_idcache_find_by_name(SilcIDCache cache, char *name,
+                              SilcIDCacheList *ret)
 {
   SilcIDCacheList list;
 
@@ -342,10 +418,8 @@ bool silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
   if (!ret)
     return TRUE;
 
-  silc_hash_table_find_foreach_ext(cache->data_table, data, 
-                                  silc_hash_data, (void *)data_len,
-                                  silc_hash_data_compare, (void *)data_len,
-                                  silc_idcache_get_all_foreach, list);
+  silc_hash_table_find_foreach(cache->name_table, name, 
+                              silc_idcache_get_all_foreach, list);
 
   if (silc_idcache_list_count(list) == 0) {
     silc_idcache_list_free(list);
@@ -357,23 +431,14 @@ bool silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
   return TRUE;
 }
 
-/* Find ID Cache entry by data. The data maybe anything that must
-   match exactly. Returns one cache entry. */
+/* Find ID Cache entry by name. Returns one cache entry. */
 
-bool silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
-                                  unsigned int data_len, 
+bool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
                                   SilcIDCacheEntry *ret)
 {
-  SilcIDCacheEntry c;
-
-  if (!silc_hash_table_find_ext(cache->data_table, data, NULL, (void *)&c,
-                               silc_hash_data, (void *)data_len,
-                               silc_hash_data_compare, (void *)data_len))
+  if (!silc_hash_table_find(cache->name_table, name, NULL, (void *)ret))
     return FALSE;
 
-  if (ret)
-    *ret = c;
-
   return TRUE;
 }
 
index 032bad702b3d3d85c1b20682194b62319b0f287a..e1c2b0636780cc981368ef8145a53c7d0c0a6e1e 100644 (file)
    This is one entry in the SILC ID Cache system. Contents of this is
    allocated outside the ID cache system, however, all the fields are 
    filled with ID cache utility functions. The ID cache system does not
-   allocate any of these fields nor free them. The system assumes that
-   the type of the ID in a specific ID Cache context are of the same
-   type.  One should not mix different types of ID's (eg. Client ID and
-   Server ID) to the same ID Cache context.
-
-   unsigned char *data
-   uint32 data_len;
-
-      The data that is usually used to find the data from the cache.
-      For example for Client ID's this is nickname.
+   allocate any of these fields nor free them.
 
    void *id
 
       The actual ID.
 
+   char name
+
+      A name associated with the ID.
+
    uint32 expire
 
       Time when this cache entry expires.  This is normal time() value
@@ -55,9 +50,8 @@
 
 */
 typedef struct {
-  unsigned char *data;
-  uint32 data_len;
   void *id;
+  char *name;
   uint32 expire;
   void *context;
 } *SilcIDCacheEntry;
@@ -84,23 +78,35 @@ typedef void (*SilcIDCacheDestructor)(SilcIDCache cache,
 SilcIDCache silc_idcache_alloc(uint32 count, SilcIdType id_type,
                               SilcIDCacheDestructor destructor);
 void silc_idcache_free(SilcIDCache cache);
-bool silc_idcache_add(SilcIDCache cache, unsigned char *data
-                     uint32 data_len, void *id, void *context, int expire);
+bool silc_idcache_add(SilcIDCache cache, char *name, void *id
+                     void *context, int expire);
 bool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old);
 bool silc_idcache_del_by_id(SilcIDCache cache, void *id);
+bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
+                               SilcHashFunction hash, 
+                               void *hash_context,
+                               SilcHashCompare compare, 
+                               void *compare_context);
 bool silc_idcache_del_by_context(SilcIDCache cache, void *context);
 bool silc_idcache_del_all(SilcIDCache cache);
 bool silc_idcache_purge(SilcIDCache cache);
 bool silc_idcache_purge_by_context(SilcIDCache cache, void *context);
 bool silc_idcache_get_all(SilcIDCache cache, SilcIDCacheList *ret);
 bool silc_idcache_find_by_id(SilcIDCache cache, void *id, 
-                            SilcIDCacheEntry *ret);
+                            SilcIDCacheList *ret);
+bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, 
+                                SilcIDCacheEntry *ret);
+bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id, 
+                                    SilcHashFunction hash, 
+                                    void *hash_context,
+                                    SilcHashCompare compare, 
+                                    void *compare_context,
+                                    SilcIDCacheEntry *ret);
 bool silc_idcache_find_by_context(SilcIDCache cache, void *context, 
                                  SilcIDCacheEntry *ret);
-bool silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data, 
-                              unsigned int data_len, SilcIDCacheList *ret);
-bool silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
-                                  unsigned int data_len, 
+bool silc_idcache_find_by_name(SilcIDCache cache, char *name, 
+                              SilcIDCacheList *ret);
+bool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
                                   SilcIDCacheEntry *ret);
 int silc_idcache_list_count(SilcIDCacheList list);
 bool silc_idcache_list_first(SilcIDCacheList list, SilcIDCacheEntry *ret);
index fa0d01577fde1ec76714da9e7160c081d65131c9..fe75b10a22af69bb059a84af03b6e930c984746e 100644 (file)
 #include "silcincludes.h"
 #include "silchashtable.h"
 
+/* Define to 1 if you want hash table debug enabled */
+#define SILC_HASH_TABLE_DEBUG 0
+
+#if SILC_HASH_TABLE_DEBUG == 1
+#define SILC_HT_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
+#else
+#define SILC_HT_DEBUG(fmt)
+#endif
+
 /* Default size of the hash table (index to prime table) */
 #define SILC_HASH_TABLE_SIZE 3
 
@@ -80,10 +89,12 @@ static uint32 silc_hash_table_primesize(uint32 size, uint32 *index)
   for (i = 0; i < sizeof(primesize); i++)
     if (primesize[i] >= size) {
       *index = i;
+      SILC_HT_DEBUG(("sizeof of the hash table is %d", primesize[*index]));
       return primesize[i];
     }
 
   *index = i - 1;
+  SILC_HT_DEBUG(("sizeof of the hash table is %d", primesize[*index]));
   return primesize[i - 1];
 }
 
@@ -98,8 +109,11 @@ silc_hash_table_find_internal(SilcHashTable ht, void *key,
                              void *compare_user_context)
 {
   SilcHashTableEntry *entry, prev = NULL;
+  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+  SILC_HT_DEBUG(("index %d key %p", i, key));
 
-  entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+  entry = &ht->table[i];
   if (compare) {
     while (*entry && !compare((*entry)->key, key, compare_user_context)) {
       prev = *entry;
@@ -129,16 +143,23 @@ silc_hash_table_find_internal_context(SilcHashTable ht, void *key,
                                      void *compare_user_context)
 {
   SilcHashTableEntry *entry, prev = NULL;
+  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
 
-  entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+  SILC_HT_DEBUG(("index %d key %p context %p", i, key, context));
+
+  entry = &ht->table[i];
   if (ht->compare) {
-    while (*entry && !compare((*entry)->key, key, compare_user_context) &&
-          (*entry)->context != context) {
+    while (*entry) {
+      if (compare((*entry)->key, key, compare_user_context) &&
+         (*entry)->context == context)
+       break;
       prev = *entry;
       entry = &(*entry)->next;
     }
   } else {
-    while (*entry && (*entry)->key != key && (*entry)->context != context) {
+    while (*entry) {
+      if ((*entry)->key == key && (*entry)->context == context)
+       break;
       prev = *entry;
       entry = &(*entry)->next;
     }
@@ -158,8 +179,11 @@ silc_hash_table_find_internal_simple(SilcHashTable ht, void *key,
                                     void *compare_user_context)
 {
   SilcHashTableEntry *entry;
+  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
 
-  entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+  SILC_HT_DEBUG(("index %d key %p", i, key));
+
+  entry = &ht->table[i];
   if (compare) {
     while (*entry && !compare((*entry)->key, key, compare_user_context))
       entry = &(*entry)->next;
@@ -185,8 +209,11 @@ silc_hash_table_find_internal_all(SilcHashTable ht, void *key,
                                  void *foreach_user_context)
 {
   SilcHashTableEntry *entry;
+  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+  SILC_HT_DEBUG(("index %d key %p", i, key));
 
-  entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+  entry = &ht->table[i];
   if (compare) {
     while (*entry) {
       if (compare((*entry)->key, key, compare_user_context))
@@ -210,10 +237,11 @@ silc_hash_table_add_internal(SilcHashTable ht, void *key, void *context,
                             void *hash_user_context)
 {
   SilcHashTableEntry *entry;
-  uint32 index = (hash ? SILC_HASH_TABLE_HASH : 
-                 SILC_HASH_TABLE_HASH_F(hash, hash_user_context));
+  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+  SILC_HT_DEBUG(("index %d key %p", i, key));
 
-  entry = &ht->table[index];
+  entry = &ht->table[i];
   if (*entry) {
     /* The entry exists already. We have a collision, add it to the
        list to avoid collision. */
@@ -226,12 +254,15 @@ silc_hash_table_add_internal(SilcHashTable ht, void *key, void *context,
       tmp = tmp->next;
     }
 
+    SILC_HT_DEBUG(("Collision; adding new key to list"));
+
     e->next = silc_calloc(1, sizeof(*e->next));
     e->next->key = key;
     e->next->context = context;
     ht->entry_count++;
   } else {
     /* New key */
+    SILC_HT_DEBUG(("New key"));
     *entry = silc_calloc(1, sizeof(**entry));
     (*entry)->key = key;
     (*entry)->context = context;
@@ -247,10 +278,11 @@ silc_hash_table_replace_internal(SilcHashTable ht, void *key, void *context,
                                 void *hash_user_context)
 {
   SilcHashTableEntry *entry;
-  uint32 index = (hash ? SILC_HASH_TABLE_HASH : 
-                 SILC_HASH_TABLE_HASH_F(hash, hash_user_context));
+  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+  SILC_HT_DEBUG(("index %d key %p", i, key));
 
-  entry = &ht->table[index];
+  entry = &ht->table[i];
   if (*entry) {
     /* The entry exists already. We have a collision, replace the old
        key and context. */
@@ -351,7 +383,8 @@ uint32 silc_hash_table_count(SilcHashTable ht)
 
 void silc_hash_table_add(SilcHashTable ht, void *key, void *context)
 {
-  silc_hash_table_add_internal(ht, key, context, NULL, NULL);
+  silc_hash_table_add_internal(ht, key, context, ht->hash, 
+                              ht->hash_user_context);
 }
 
 /* Same as above but with specific hash function and user context. */
@@ -369,7 +402,8 @@ void silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context,
 
 void silc_hash_table_replace(SilcHashTable ht, void *key, void *context)
 {
-  silc_hash_table_replace_internal(ht, key, context, NULL, NULL);
+  silc_hash_table_replace_internal(ht, key, context, ht->hash, 
+                                  ht->hash_user_context);
 }
 
 /* Same as above but with specific hash function. */
@@ -694,3 +728,45 @@ void silc_hash_table_rehash(SilcHashTable ht, uint32 new_size)
   /* Remove old table */
   silc_free(table);
 }
+
+/* Same as above but with specific hash function. */
+
+void silc_hash_table_rehash_ext(SilcHashTable ht, uint32 new_size,
+                               SilcHashFunction hash, 
+                               void *hash_user_context)
+{
+  int i;
+  SilcHashTableEntry *table, e, tmp;
+  uint32 table_size, size_index;
+
+  SILC_HT_DEBUG(("Rehashing"));
+
+  /* Take old hash table */
+  table = ht->table;
+  table_size = ht->table_size;
+
+  /* Allocate new table */
+  ht->table = silc_calloc(new_size ? silc_hash_table_primesize(new_size,
+                                                              &size_index) :
+                         silc_hash_table_primesize(ht->entry_count,
+                                                   &size_index),
+                         sizeof(*ht->table));
+  ht->table_size = size_index;
+
+  /* Rehash */
+  for (i = 0; i < primesize[table_size]; i++) {
+    e = table[i];
+    while (e) {
+      silc_hash_table_add_ext(ht, e->key, e->context, hash, 
+                             hash_user_context);
+      tmp = e;
+      e = e->next;
+
+      /* Remove old entry */
+      silc_free(tmp);
+    }
+  }
+
+  /* Remove old table */
+  silc_free(table);
+}
index 6b76dac468d53adb9a072a9329ebf36c2afc5d6a..4bda91ab2b198428cd127e1d4c990e40297a88b3 100644 (file)
@@ -101,5 +101,8 @@ void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
                                      void *compare_user_context,
                                      SilcHashForeach foreach, 
                                      void *foreach_user_context);
+void silc_hash_table_rehash_ext(SilcHashTable ht, uint32 new_size,
+                               SilcHashFunction hash, 
+                               void *hash_user_context);
 
 #endif
index 122e148db8069c26d6148601394af576dd7820a9..10b37f09df625321dcbc73f42d4236ca782ad934 100644 (file)
@@ -769,7 +769,10 @@ char *silc_get_real_name()
   return realname;
 }
 
-/* Basic has function to hash strings. May be used with the SilcHashTable. */
+/* Basic has function to hash strings. May be used with the SilcHashTable. 
+   Note that this lowers the characters of the string (with tolower()) so
+   this is used usually with nicknames, channel and server names to provide
+   case insensitive keys. */
 
 uint32 silc_hash_string(void *key, void *user_context)
 {
@@ -777,7 +780,7 @@ uint32 silc_hash_string(void *key, void *user_context)
   uint32 h = 0, g;
   
   while (*s != '\0') {
-    h = (h << 4) + toupper(*s);
+    h = (h << 4) + tolower(*s);
     if ((g = h & 0xf0000000)) {
       h = h ^ (g >> 24);
       h = h ^ g;
@@ -808,28 +811,33 @@ uint32 silc_hash_id(void *key, void *user_context)
 {
   SilcIdType id_type = (SilcIdType)(uint32)user_context;
   uint32 h = 0;
+  int i;
 
   switch (id_type) {
   case SILC_ID_CLIENT:
     {
       SilcClientID *id = (SilcClientID *)key;
-      int i;
-      uint32 h;
-      
-      h = id->rnd;
-      for (i = 0; i < sizeof(id->hash); i++)
-       h ^= id->hash[i];
-      for (i = 0; i < id->ip.data_len; i++)
-       h ^= id->ip.data[i];
-      
+      uint32 g;
+  
+      /* The client ID is hashed by hashing the hash of the ID 
+        (which is a truncated MD5 hash of the nickname) so that we
+        can access the entry from the cache with both Client ID but
+        with just a hash from the ID as well. */
+
+      for (i = 0; i < sizeof(id->hash); i++) {
+       h = (h << 4) + id->hash[i];
+       if ((g = h & 0xf0000000)) {
+         h = h ^ (g >> 24);
+         h = h ^ g;
+       }
+      }
+
       return h;
     }
     break;
   case SILC_ID_SERVER:
     {
       SilcServerID *id = (SilcServerID *)key;
-      int i;
-      uint32 h;
       
       h = id->port * id->rnd;
       for (i = 0; i < id->ip.data_len; i++)
@@ -841,8 +849,6 @@ uint32 silc_hash_id(void *key, void *user_context)
   case SILC_ID_CHANNEL:
     {
       SilcChannelID *id = (SilcChannelID *)key;
-      int i;
-      uint32 h;
       
       h = id->port * id->rnd;
       for (i = 0; i < id->ip.data_len; i++)
@@ -873,12 +879,30 @@ uint32 silc_hash_data(void *key, void *user_context)
   return h;
 }
 
-/* Compares two ID's. May be used as SilcHashTable comparison function. */
+/* Compares two strings. May be used as SilcHashTable comparison function. */
+
+bool silc_hash_string_compare(void *key1, void *key2, void *user_context)
+{
+  return !strcasecmp((char *)key1, (char *)key2);
+}
+
+/* Compares two ID's. May be used as SilcHashTable comparison function. 
+   The Client ID's compares only the hash of the Client ID not any other
+   part of the Client ID. Other ID's are fully compared. */
 
 bool silc_hash_id_compare(void *key1, void *key2, void *user_context)
 {
   SilcIdType id_type = (SilcIdType)(uint32)user_context;
-  return SILC_ID_COMPARE_TYPE(key1, key2, id_type);
+  return (id_type == SILC_ID_CLIENT ? 
+         SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) :
+         SILC_ID_COMPARE_TYPE(key1, key2, id_type));
+}
+
+/* Compare two Client ID's entirely and not just the hash from the ID. */
+
+bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context)
+{
+  return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT);
 }
 
 /* Compares binary data. May be used as SilcHashTable comparison function. */
index 55fb3b0c2815fe340e301b5ae3297a3476967bc2..4556699cd355f35995f2a72445cb273060a3db39 100644 (file)
@@ -55,7 +55,9 @@ uint32 silc_hash_uint(void *key, void *user_context);
 uint32 silc_hash_ptr(void *key, void *user_context);
 uint32 silc_hash_id(void *key, void *user_context);
 uint32 silc_hash_data(void *key, void *user_context);
+bool silc_hash_string_compare(void *key1, void *key2, void *user_context);
 bool silc_hash_id_compare(void *key1, void *key2, void *user_context);
+bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context);
 bool silc_hash_data_compare(void *key1, void *key2, void *user_context);
 
 #endif