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
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;
/* 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;
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),
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;
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;
}
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)
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);
+}