updates.
[silc.git] / apps / silcd / idlist.c
index 507c73022f25c950f48b1700c7a0ddbc2b5ea487..e50a87be957de6d7c761f67e9acd11c1ebddde73 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2001 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -116,7 +116,8 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
   if (!id)
     return NULL;
 
-  SILC_LOG_DEBUG(("Finding server by ID"));
+  SILC_LOG_DEBUG(("Server ID (%s)",
+                 silc_id_render(id, SILC_ID_SERVER)));
 
   if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, 
                                   SILC_ID_SERVER, &id_cache))
@@ -171,6 +172,9 @@ void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
       silc_free(entry->server_name);
     if (entry->id)
       silc_free(entry->id);
+
+    memset(entry, 'F', sizeof(*entry));
+    silc_free(entry);
   }
 }
 
@@ -182,7 +186,12 @@ void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 
 /* Add new client entry. This adds the client entry to ID cache system
    and returns the allocated client entry or NULL on error.  This is
-   called when new client connection is accepted to the server. */
+   called when new client connection is accepted to the server. If The
+   `router' is provided then the all server routines assume that the client
+   is not directly connected local client but it has router set and is
+   remote.  If this is the case then `connection' must be NULL.  If, on the
+   other hand, the `connection' is provided then the client is assumed
+   to be directly connected local client and `router' must be NULL. */
 
 SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname, 
@@ -215,13 +224,14 @@ silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
 /* Free client entry. This free's everything and removes the entry
    from ID cache. Call silc_idlist_del_data before calling this one. */
 
-void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
+int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 {
   if (entry) {
     /* Remove from cache */
     if (entry->id)
-      silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT, 
-                            (void *)entry->id);
+      if (!silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT, 
+                                 (void *)entry->id))
+       return FALSE;
 
     /* Free data */
     if (entry->nickname)
@@ -232,7 +242,14 @@ void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
       silc_free(entry->userinfo);
     if (entry->id)
       silc_free(entry->id);
+
+    memset(entry, 'F', sizeof(*entry));
+    silc_free(entry);
+
+    return TRUE;
   }
+
+  return FALSE;
 }
 
 /* Returns all clients matching requested nickname. Number of clients is
@@ -313,7 +330,7 @@ silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
   SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry client = NULL;
 
-  SILC_LOG_DEBUG(("Finding client by nickname"));
+  SILC_LOG_DEBUG(("Client by nickname"));
 
   if (server) {
     if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
@@ -344,6 +361,8 @@ silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
       *ret_entry = id_cache;
   }
 
+  SILC_LOG_DEBUG(("Found"));
+
   return client;
 }
 
@@ -358,7 +377,7 @@ silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
   SilcClientEntry client = NULL;
   unsigned char hash[32];
 
-  SILC_LOG_DEBUG(("Finding client by hash"));
+  SILC_LOG_DEBUG(("Client by hash"));
 
   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
 
@@ -389,6 +408,8 @@ silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
   if (ret_entry)
     *ret_entry = id_cache;
 
+  SILC_LOG_DEBUG(("Found"));
+
   return client;
 }
 
@@ -404,7 +425,8 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
   if (!id)
     return NULL;
 
-  SILC_LOG_DEBUG(("Finding client by ID"));
+  SILC_LOG_DEBUG(("Client ID (%s)", 
+                 silc_id_render(id, SILC_ID_CLIENT)));
 
   if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id, 
                                   SILC_ID_CLIENT, &id_cache))
@@ -415,6 +437,8 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
   if (ret_entry)
     *ret_entry = id_cache;
 
+  SILC_LOG_DEBUG(("Found"));
+
   return client;
 }
 
@@ -450,6 +474,8 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
     silc_idcache_sort_by_data(id_list->clients);
   }
 
+  SILC_LOG_DEBUG(("Replaced"));
+
   return client;
 }
 
@@ -491,15 +517,16 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
 
 /* Free channel entry.  This free's everything. */
 
-void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
+int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
 {
   if (entry) {
     SilcChannelClientEntry chl;
 
     /* Remove from cache */
     if (entry->id)
-      silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL, 
-                            (void *)entry->id);
+      if (!silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL, 
+                                 (void *)entry->id))
+       return FALSE;
 
     /* Free data */
     if (entry->channel_name)
@@ -514,14 +541,19 @@ void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
       memset(entry->key, 0, entry->key_len / 8);
       silc_free(entry->key);
     }
-    memset(entry->iv, 0, sizeof(entry->iv));
     
     silc_list_start(entry->user_list);
     while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
       silc_list_del(entry->user_list, chl);
       silc_free(chl);
     }
+
+    memset(entry, 'F', sizeof(*entry));
+    silc_free(entry);
+    return TRUE;
   }
+
+  return FALSE;
 }
 
 /* Finds channel by channel name. Channel names are unique and they
@@ -535,7 +567,7 @@ silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
   SilcIDCacheEntry id_cache = NULL;
   SilcChannelEntry channel;
 
-  SILC_LOG_DEBUG(("Finding channel by name"));
+  SILC_LOG_DEBUG(("Channel by name"));
 
   if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
     return NULL;
@@ -552,6 +584,8 @@ silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
 
   silc_idcache_list_free(list);
 
+  SILC_LOG_DEBUG(("Found"));
+
   return channel;
 }
 
@@ -567,7 +601,8 @@ silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
   if (!id)
     return NULL;
 
-  SILC_LOG_DEBUG(("Finding channel by ID"));
+  SILC_LOG_DEBUG(("Channel ID (%s)",
+                 silc_id_render(id, SILC_ID_CHANNEL)));
 
   if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id, 
                                   SILC_ID_CHANNEL, &id_cache))
@@ -578,5 +613,34 @@ silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
   if (ret_entry)
     *ret_entry = id_cache;
 
+  SILC_LOG_DEBUG(("Found"));
+
+  return channel;
+}
+
+/* Replaces old Channel ID with new one. This is done when router forces
+   normal server to change Channel ID. */
+
+SilcChannelEntry
+silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
+                              SilcChannelID *new_id)
+{
+  SilcIDCacheEntry id_cache = NULL;
+  SilcChannelEntry channel;
+
+  if (!old_id || !new_id)
+    return NULL;
+
+  SILC_LOG_DEBUG(("Replacing Channel ID"));
+
+  if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id, 
+                                  SILC_ID_CHANNEL, &id_cache))
+    return NULL;
+
+  channel = (SilcChannelEntry)id_cache->context;
+  silc_free(channel->id);
+  channel->id = new_id;
+  id_cache->id = (void *)new_id;
+
   return channel;
 }