updates.
[silc.git] / apps / silcd / serverid.c
index 12cebb6a57ec3d0ebe26ea4dbd73f36c28b651ec..fb29b468412e6f2b828f4949aacd2b222385094e 100644 (file)
@@ -20,6 +20,7 @@
 /* $Id$ */
 
 #include "serverincludes.h"
+#include "server_internal.h"
 
 /* Creates a Server ID. Newly created Server ID is returned to the
    new_id argument. */
@@ -53,13 +54,19 @@ void silc_id_create_server_id(int sock, SilcRng rng, SilcServerID **new_id)
   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
 }
 
-/* Creates Client ID */
+/* Creates Client ID. This assures that there are no collisions in the
+   created Client IDs.  If the collision would occur (meaning that there
+   are 2^8 occurences of the `nickname' this will return FALSE, and the
+   caller must recall the function with different nickname. If this returns
+   TRUE the new ID was created successfully. */
 
-void silc_id_create_client_id(SilcServerID *server_id, SilcRng rng,
+bool silc_id_create_client_id(SilcServer server,
+                             SilcServerID *server_id, SilcRng rng,
                              SilcHash md5hash, char *nickname, 
                              SilcClientID **new_id)
 {
   unsigned char hash[16];
+  bool finding = FALSE;
 
   SILC_LOG_DEBUG(("Creating new Client ID"));
 
@@ -74,14 +81,42 @@ void silc_id_create_client_id(SilcServerID *server_id, SilcRng rng,
   (*new_id)->rnd = silc_rng_get_byte(rng);
   memcpy((*new_id)->hash, hash, CLIENTID_HASH_LEN);
 
+  /* Assure that the ID does not exist already */
+  while (1) {
+    if (!silc_idlist_find_client_by_id(server->local_list, 
+                                      *new_id, FALSE, NULL))
+      if (!silc_idlist_find_client_by_id(server->global_list, 
+                                        *new_id, FALSE, NULL))
+       break;
+
+    /* The ID exists, start increasing the rnd from 0 until we find a
+       ID that does not exist. If we wrap and it still exists then we
+       will return FALSE and the caller must send some other nickname
+       since this cannot be used anymore. */
+    (*new_id)->rnd++;
+
+    if (finding && (*new_id)->rnd == 0)
+      return FALSE;
+
+    if (!finding) {
+      (*new_id)->rnd = 0;
+      finding = TRUE;
+    }
+  }
+
   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_CLIENT)));
+
+  return TRUE;
 }
 
 /* Creates Channel ID */
 
-void silc_id_create_channel_id(SilcServerID *router_id, SilcRng rng,
+bool silc_id_create_channel_id(SilcServer server,
+                              SilcServerID *router_id, SilcRng rng,
                               SilcChannelID **new_id)
 {
+  bool finding = TRUE;
+
   SILC_LOG_DEBUG(("Creating new Channel ID"));
 
   *new_id = silc_calloc(1, sizeof(**new_id));
@@ -92,5 +127,26 @@ void silc_id_create_channel_id(SilcServerID *router_id, SilcRng rng,
   (*new_id)->port = router_id->port;
   (*new_id)->rnd = silc_rng_get_rn16(rng);
 
+  /* Assure that the ID does not exist already */
+  while (1) {
+    if (!silc_idlist_find_channel_by_id(server->local_list, 
+                                       *new_id, NULL))
+      if (!silc_idlist_find_channel_by_id(server->global_list, 
+                                         *new_id, NULL))
+       break;
+    
+    (*new_id)->rnd++;
+    
+    if (finding && (*new_id)->rnd == 0)
+      return FALSE;
+    
+    if (!finding) {
+      (*new_id)->rnd = 0;
+      finding = TRUE;
+    }
+  }
+
   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_CHANNEL)));
+
+  return TRUE;
 }