Moved SILC id utility functions from utility library.
[silc.git] / lib / silccore / silcid.c
index 1e5727bc215bd96d94831b3aa7119e9e5b71ff97..609814bddfd7f549412f359403a9f9c4aa27b288 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2005 Pekka Riikonen
+  Copyright (C) 1997 - 2008 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
@@ -69,7 +69,7 @@ SilcIDPayload silc_id_payload_parse(const unsigned char *payload,
     goto err;
 
   ret = silc_buffer_unformat(&buffer,
-                            SILC_STR_UI_XNSTRING_ALLOC(&newp->id, newp->len),
+                            SILC_STR_DATA_ALLOC(&newp->id, newp->len),
                             SILC_STR_END);
   if (ret == -1)
     goto err;
@@ -85,8 +85,7 @@ SilcIDPayload silc_id_payload_parse(const unsigned char *payload,
 /* Return the ID directly from the raw payload data. */
 
 SilcBool silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len,
-                                 SilcIdType *ret_type, void *ret_id,
-                                 SilcUInt32 ret_id_size)
+                                 SilcID *ret_id)
 {
   SilcBufferStruct buffer;
   SilcIdType type;
@@ -94,6 +93,9 @@ SilcBool silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len,
   unsigned char *id_data;
   int ret;
 
+  if (!ret_id)
+    return FALSE;
+
   silc_buffer_set(&buffer, (unsigned char *)data, len);
   ret = silc_buffer_unformat(&buffer,
                             SILC_STR_UI_SHORT(&type),
@@ -111,16 +113,26 @@ SilcBool silc_id_payload_parse_id(const unsigned char *data, SilcUInt32 len,
     goto err;
 
   ret = silc_buffer_unformat(&buffer,
-                            SILC_STR_UI_XNSTRING(&id_data, idlen),
+                            SILC_STR_DATA(&id_data, idlen),
                             SILC_STR_END);
   if (ret == -1)
     goto err;
 
-  if (!silc_id_str2id(id_data, idlen, type, ret_id, ret_id_size))
-    goto err;
-
-  if (ret_type)
-    *ret_type = type;
+  ret_id->type = type;
+
+  if (type == SILC_ID_CLIENT) {
+    if (!silc_id_str2id(id_data, idlen, type, &ret_id->u.client_id,
+                       sizeof(SilcClientID)))
+      goto err;
+  } else if (type == SILC_ID_SERVER) {
+    if (!silc_id_str2id(id_data, idlen, type, &ret_id->u.server_id,
+                       sizeof(SilcServerID)))
+      goto err;
+  } else {
+    if (!silc_id_str2id(id_data, idlen, type, &ret_id->u.channel_id,
+                       sizeof(SilcChannelID)))
+      goto err;
+  }
 
   return TRUE;
 
@@ -155,7 +167,7 @@ SilcBuffer silc_id_payload_encode_data(const unsigned char *id,
   silc_buffer_format(buffer,
                     SILC_STR_UI_SHORT(type),
                     SILC_STR_UI_SHORT(id_len),
-                    SILC_STR_UI_XNSTRING(id, id_len),
+                    SILC_STR_DATA(id, id_len),
                     SILC_STR_END);
   return buffer;
 }
@@ -328,6 +340,36 @@ SilcBool silc_id_str2id(const unsigned char *id, SilcUInt32 id_len,
   return FALSE;
 }
 
+/* Converts string to ID */
+
+SilcBool silc_id_str2id2(const unsigned char *id, SilcUInt32 id_len,
+                        SilcIdType type, SilcID *ret_id)
+{
+  if (!ret_id)
+    return FALSE;
+
+  ret_id->type = type;
+
+  switch (type) {
+  case SILC_ID_CLIENT:
+    return silc_id_str2id(id, id_len, type, &ret_id->u.client_id,
+                         sizeof(ret_id->u.client_id));
+    break;
+
+  case SILC_ID_SERVER:
+    return silc_id_str2id(id, id_len, type, &ret_id->u.server_id,
+                         sizeof(ret_id->u.server_id));
+    break;
+
+  case SILC_ID_CHANNEL:
+    return silc_id_str2id(id, id_len, type, &ret_id->u.channel_id,
+                         sizeof(ret_id->u.channel_id));
+    break;
+  }
+
+  return FALSE;
+}
+
 /* Returns length of the ID */
 
 SilcUInt32 silc_id_get_len(const void *id, SilcIdType type)
@@ -383,3 +425,101 @@ void *silc_id_dup(const void *id, SilcIdType type)
 
   return NULL;
 }
+
+/**************************** Utility functions *****************************/
+
+/* Hash a ID. The `user_context' is the ID type. */
+
+SilcUInt32 silc_hash_id(void *key, void *user_context)
+{
+  SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
+  SilcUInt32 h = 0;
+  int i;
+
+  switch (id_type) {
+  case SILC_ID_CLIENT:
+    {
+      SilcClientID *id = (SilcClientID *)key;
+
+      /* 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. */
+      return silc_hash_client_id_hash(id->hash, NULL);
+    }
+    break;
+  case SILC_ID_SERVER:
+    {
+      SilcServerID *id = (SilcServerID *)key;
+
+      h = id->port * id->rnd;
+      for (i = 0; i < id->ip.data_len; i++)
+       h ^= id->ip.data[i];
+
+      return h;
+    }
+    break;
+  case SILC_ID_CHANNEL:
+    {
+      SilcChannelID *id = (SilcChannelID *)key;
+
+      h = id->port * id->rnd;
+      for (i = 0; i < id->ip.data_len; i++)
+       h ^= id->ip.data[i];
+
+      return h;
+    }
+    break;
+  default:
+    break;
+  }
+
+  return h;
+}
+
+/* Hash Client ID's hash. */
+
+SilcUInt32 silc_hash_client_id_hash(void *key, void *user_context)
+{
+  int i;
+  unsigned char *hash = key;
+  SilcUInt32 h = 0, g;
+
+  for (i = 0; i < CLIENTID_HASH_LEN; i++) {
+    h = (h << 4) + hash[i];
+    if ((g = h & 0xf0000000)) {
+      h = h ^ (g >> 24);
+      h = h ^ g;
+    }
+  }
+
+  return h;
+}
+
+/* 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. */
+
+SilcBool silc_hash_id_compare(void *key1, void *key2, void *user_context)
+{
+  SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
+  return (id_type == SILC_ID_CLIENT ?
+         SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) :
+         SILC_ID_COMPARE_TYPE(key1, key2, id_type));
+}
+
+/* Compares two ID's. Compares full IDs. */
+
+SilcBool silc_hash_id_compare_full(void *key1, void *key2, void *user_context)
+{
+  SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
+  return SILC_ID_COMPARE_TYPE(key1, key2, id_type);
+}
+
+/* Compare two Client ID's entirely and not just the hash from the ID. */
+
+SilcBool silc_hash_client_id_compare(void *key1, void *key2,
+                                    void *user_context)
+{
+  return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT);
+}