A LOT updates. Cannot separate. :)
[silc.git] / apps / silcd / idlist.c
index bc198fa0f8bc62f3e97784ad410ccdbb189b733d..358bef33f467826ace5549b419c4c4dc7652fcf5 100644 (file)
   GNU General Public License for more details.
 
 */
-/*
- * $Id$
- * $Log$
- * Revision 1.6  2000/07/17 11:47:30  priikone
- *     Added command lagging support. Added idle counting support.
- *
- * Revision 1.5  2000/07/12 05:59:41  priikone
- *     Major rewrite of ID Cache system. Support added for the new
- *     ID cache system. Major rewrite of ID List stuff on server.  All
- *     SilcXXXList's are now called SilcXXXEntry's and they are pointers
- *     by default. A lot rewritten ID list functions.
- *
- * Revision 1.4  2000/07/06 07:16:13  priikone
- *     Added SilcPublicKey's
- *
- * Revision 1.3  2000/07/05 06:14:01  priikone
- *     Global costemic changes.
- *
- * Revision 1.2  2000/07/03 05:52:11  priikone
- *     Fixed typo and a bug.
- *
- * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
- *     Imported from internal CVS/Added Log headers.
- *
- *
- */
+/* $Id$ */
 
 #include "serverincludes.h"
 #include "idlist.h"
@@ -91,6 +66,54 @@ silc_idlist_add_server(SilcIDList id_list,
   return server;
 }
 
+/* Finds server by Server ID */
+
+SilcServerEntry
+silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id)
+{
+  SilcIDCacheEntry id_cache = NULL;
+  SilcServerEntry server;
+
+  if (!id)
+    return NULL;
+
+  SILC_LOG_DEBUG(("Finding server by ID"));
+
+  if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, 
+                                  SILC_ID_SERVER, &id_cache))
+    return NULL;
+
+  server = (SilcServerEntry)id_cache->context;
+
+  return server;
+}
+
+/* Replaces old Server ID with new one */ 
+
+SilcServerEntry
+silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
+                             SilcServerID *new_id)
+{
+  SilcIDCacheEntry id_cache = NULL;
+  SilcServerEntry server;
+
+  if (!old_id || !new_id)
+    return NULL;
+
+  SILC_LOG_DEBUG(("Replacing Server ID"));
+
+  if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id, 
+                                  SILC_ID_SERVER, &id_cache))
+    return NULL;
+
+  server = (SilcServerEntry)id_cache->context;
+  silc_free(server->id);
+  server->id = new_id;
+  id_cache->id = (void *)new_id;
+
+  return server;
+}
+
 /******************************************************************************
 
                           Client entry functions
@@ -168,6 +191,38 @@ void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
   }
 }
 
+/* Returns all clients matching requested nickname. Number of clients is
+   returned to `clients_count'. Caller must free the returned table. */
+
+SilcClientEntry *
+silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
+                                   char *server, unsigned int *clients_count)
+{
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcClientEntry *clients;
+  int i;
+
+  if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
+    return NULL;
+
+  clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
+
+  i = 0;
+  silc_idcache_list_first(list, &id_cache);
+  clients[i++] = (SilcClientEntry)id_cache->context;
+
+  while (silc_idcache_list_next(list, &id_cache))
+    clients[i++] = (SilcClientEntry)id_cache->context;
+  
+  silc_idcache_list_free(list);
+  
+  if (clients_count)
+    *clients_count = i;
+
+  return clients;
+}
+
 /* Finds client entry by nickname. */
 
 SilcClientEntry
@@ -195,10 +250,10 @@ silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
     }
 #endif
 
+   silc_idcache_list_free(list);
+
    if (!client)
      return NULL;
-
-   silc_idcache_list_free(list);
   } else {
     if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
       return NULL;
@@ -212,11 +267,43 @@ silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
 /* Finds client by nickname hash. */
 
 SilcClientEntry
-silc_idlist_find_client_by_hash(SilcIDList id_list, unsigned char *hash,
+silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
                                SilcHash md5hash)
 {
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcClientEntry client = NULL;
+  unsigned char hash[32];
+
+  SILC_LOG_DEBUG(("Finding client by hash"));
+
+  silc_hash_make(md5hash, nickname, strlen(nickname), hash);
+
+  if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY, 
+                              SILC_ID_CLIENT, &list))
+    return NULL;
 
-  return NULL;
+  if (!silc_idcache_list_first(list, &id_cache)) {
+    silc_idcache_list_free(list);
+    return NULL;
+  }
+
+  while (id_cache) {
+    client = (SilcClientEntry)id_cache->context;
+    
+    if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
+      break;
+
+    id_cache = NULL;
+    client = NULL;
+
+    if (!silc_idcache_list_next(list, &id_cache))
+      break;
+  }
+  
+  silc_idcache_list_free(list);
+
+  return client;
 }
 
 /* Finds client by Client ID */
@@ -241,6 +328,33 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
   return client;
 }
 
+/* Replaces old Client ID with new one */
+
+SilcClientEntry
+silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
+                             SilcClientID *new_id)
+{
+  SilcIDCacheEntry id_cache = NULL;
+  SilcClientEntry client;
+
+  if (!old_id || !new_id)
+    return NULL;
+
+  SILC_LOG_DEBUG(("Replacing Client ID"));
+
+  if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id, 
+                                  SILC_ID_CLIENT, &id_cache))
+    return NULL;
+
+  client = (SilcClientEntry)id_cache->context;
+  silc_free(client->id);
+  client->id = new_id;
+  id_cache->id = (void *)new_id;
+
+  return client;
+}
+
+
 /******************************************************************************
 
                           Channel entry functions
@@ -263,6 +377,8 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
   channel->id = id;
   channel->router = router;
   channel->channel_key = channel_key;
+  silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct, 
+                next);
 
   if (!silc_idcache_add(id_list->channels, channel->channel_name, 
                        SILC_ID_CHANNEL, (void *)channel->id, 
@@ -279,6 +395,8 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
 void 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, 
@@ -298,9 +416,12 @@ void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
       silc_free(entry->key);
     }
     memset(entry->iv, 0, sizeof(entry->iv));
-
-    if (entry->user_list_count)
-      silc_free(entry->user_list);
+    
+    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);
+    }
   }
 }
 
@@ -319,8 +440,10 @@ silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
   if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
     return NULL;
   
-  if (!silc_idcache_list_first(list, &id_cache))
+  if (!silc_idcache_list_first(list, &id_cache)) {
+    silc_idcache_list_free(list);
     return NULL;
+  }
 
   channel = (SilcChannelEntry)id_cache->context;