+Sat May 19 16:30:03 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Removed the `data' and `data_len' arguments from the ID Cache
+ interfaces and added `name' argument. ID Cache does not handle
+ anymore the binary data only a names associated with given ID.
+
+ * When hashing a Client ID with silc_hash_id the entire ID is
+ not hashed anymore, instead only the hash of the Client ID is
+ hashed. This way we can access the Client ID from the cache
+ with Client ID but with the hash of the ID (which is a hash of
+ the nickname) as well without any difference in performance.
+
+ Added also silc_idcache_find_by_id_one_ext to do one on one
+ searching when we have the actual ID. Added also function
+ silc_hash_client_id_compare. The affected files are
+ lib/silccore/idcache.[ch] and lib/silcutil/silcutil.[ch].
+
+ * When hashing the name associated with a ID it is always done
+ in lowercase. This way we can access the cache without worrying
+ about case-sensitivity, even though, for example nicknames are
+ case sensitive.
+
+ * Fixed a bug in server with channel message sending. It put
+ wrong ID type as destination ID. The affected file
+ silcd/packet_send.c.
+
+ * silc_idcache_del_by_context now deletes from all hash tables
+ by context. Affected file lib/silccore/idcache.c.
+
+Fri May 18 17:42:00 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Changed the client library to use the new ID Cache interface.
+ Changes around the source tree.
+
+ * Added silc_hash_table_rehash_ext to rehash with specific
+ hash function. Affected file lib/silcutil/silchashtable.[ch].
+
+ * Added silc_hash_string_compare to compare two strings in the
+ hash table. Affected file lib/silcutil/silcutil.[ch].
+
Fri May 18 11:18:45 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Added new function silc_idcache_del_by_context into the
new_id);
/* Remove old cache entry */
- silc_idcache_del_by_id(server->local_list->clients, client->id);
+ silc_idcache_del_by_context(server->local_list->clients, client);
oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* Update client cache */
silc_idcache_add(server->local_list->clients, client->nickname,
- strlen(client->nickname), client->id,
- (void *)client, FALSE);
+ client->id, (void *)client, FALSE);
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
+ client = silc_idlist_add_client(server->global_list, nick,
strdup(username),
strdup(realname), client_id,
cmd->sock->user_data, NULL);
silc_idcache_del_by_context(global ? server->global_list->clients :
server->local_list->clients, client);
silc_idcache_add(global ? server->global_list->clients :
- server->local_list->clients, nick, strlen(nick),
- client->id, client, FALSE);
+ server->local_list->clients, nick, client->id,
+ client, FALSE);
silc_free(client_id);
}
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
+ client = silc_idlist_add_client(server->global_list, nick,
strdup(username), strdup(realname),
silc_id_dup(client_id, SILC_ID_CLIENT),
cmd->sock->user_data, NULL);
silc_idcache_del_by_context(global ? server->global_list->clients :
server->local_list->clients, client);
silc_idcache_add(global ? server->global_list->clients :
- server->local_list->clients, nick, strlen(nick),
- client->id, client, FALSE);
+ server->local_list->clients, nick, client->id,
+ client, FALSE);
}
silc_free(client_id);
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick, strlen(nick),
+ client = silc_idlist_add_client(server->global_list, nick,
username ? strdup(username) : NULL, NULL,
client_id, cmd->sock->user_data, NULL);
client->data.registered = TRUE;
silc_idcache_del_by_context(global ? server->global_list->clients :
server->local_list->clients, client);
silc_idcache_add(global ? server->global_list->clients :
- server->local_list->clients, nick, strlen(nick),
- client->id, client, FALSE);
+ server->local_list->clients, nick, client->id,
+ client, FALSE);
}
silc_free(client_id);
}
server->connection = connection;
if (!silc_idcache_add(id_list->servers, server->server_name,
- server->server_name ? strlen(server->server_name) : 0,
(void *)server->id, (void *)server, FALSE)) {
silc_free(server);
return NULL;
SILC_LOG_DEBUG(("Server ID (%s)",
silc_id_render(id, SILC_ID_SERVER)));
- if (!silc_idcache_find_by_id(id_list->servers, (void *)id,
- &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
+ &id_cache))
return NULL;
server = (SilcServerEntry)id_cache->context;
SILC_LOG_DEBUG(("Server by name `%s'", name));
- if (!silc_idcache_find_by_data_one(id_list->servers, name, strlen(name),
- &id_cache))
+ if (!silc_idcache_find_by_name_one(id_list->servers, name, &id_cache))
return NULL;
server = (SilcServerEntry)id_cache->context;
server = (SilcServerEntry)id_cache->context;
sock = (SilcSocketConnection)server->connection;
- if (sock && ((sock->hostname && !strcmp(sock->hostname, hostname)) ||
- (sock->ip && !strcmp(sock->ip, hostname)))
+ if (sock && ((sock->hostname && !strcasecmp(sock->hostname, hostname)) ||
+ (sock->ip && !strcasecmp(sock->ip, hostname)))
&& sock->port == port)
break;
SILC_LOG_DEBUG(("Replacing Server ID"));
- if (!silc_idcache_find_by_id(id_list->servers, (void *)old_id, &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
+ &id_cache))
return NULL;
server = (SilcServerEntry)id_cache->context;
silc_free(server->id);
server->id = new_id;
- id_cache->id = (void *)new_id;
+
+ /* Remove the old entry and add a new one */
+ silc_idcache_del_by_context(id_list->servers, server);
+ silc_idcache_add(id_list->servers, server->server_name, server->id,
+ server, FALSE);
SILC_LOG_DEBUG(("Found"));
to be directly connected local client and `router' must be NULL. */
SilcClientEntry
-silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
- uint32 nickname_len, char *username,
+silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
SilcServerEntry router, void *connection)
{
silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
client_list);
- if (!silc_idcache_add(id_list->clients, nickname, nickname_len,
- (void *)client->id, (void *)client, FALSE)) {
+ if (!silc_idcache_add(id_list->clients, nickname, (void *)client->id,
+ (void *)client, FALSE)) {
silc_free(client);
return NULL;
}
if (entry) {
/* Remove from cache */
if (entry->id)
- if (!silc_idcache_del_by_id(id_list->clients, (void *)entry->id))
+ if (!silc_idcache_del_by_context(id_list->clients, entry))
return FALSE;
/* Free data */
SILC_LOG_DEBUG(("Start"));
- if (!silc_idcache_find_by_data(id_list->clients, nickname, strlen(nickname),
- &list))
+ if (!silc_idcache_find_by_name(id_list->clients, nickname, &list))
return FALSE;
*clients = silc_realloc(*clients,
return TRUE;
}
-/* Returns all clients matching requested nickname. Number of clients is
- returned to `clients_count'. Caller must free the returned table. */
-/* XXX This actually checks the data, which can be hash of the nickname
- but is not if the client is local client. Global client on global
- list may have hash. Thus, this is not fully reliable function.
- Instead this should probably check the hash from the list of client ID's. */
+/* Returns all clients matching requested nickname hash. Number of clients
+ is returned to `clients_count'. Caller must free the returned table. */
int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
SilcHash md5hash,
SilcIDCacheEntry id_cache = NULL;
unsigned char hash[32];
int i;
+ SilcClientID client_id;
SILC_LOG_DEBUG(("Start"));
silc_hash_make(md5hash, nickname, strlen(nickname), hash);
- if (!silc_idcache_find_by_data(id_list->clients, hash,
- md5hash->hash->hash_len, &list))
+ memset(&client_id, 0, sizeof(client_id));
+ memcpy(&client_id.hash, hash, sizeof(client_id.hash));
+ if (!silc_idcache_find_by_id(id_list->clients, &client_id, &list))
return FALSE;
*clients = silc_realloc(*clients,
SILC_LOG_DEBUG(("Client ID (%s)",
silc_id_render(id, SILC_ID_CLIENT)));
- if (!silc_idcache_find_by_id(id_list->clients, (void *)id, &id_cache))
+ /* Do extended search since the normal ID comparison function for
+ Client ID's compares only the hash from the Client ID and not the
+ entire ID. The silc_hash_client_id_compare compares the entire
+ Client ID as we want to find one specific Client ID. */
+ if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache))
return NULL;
client = (SilcClientEntry)id_cache->context;
SILC_LOG_DEBUG(("Replacing Client ID"));
- if (!silc_idcache_find_by_id(id_list->clients, (void *)old_id, &id_cache))
+ /* Do extended search since the normal ID comparison function for
+ Client ID's compares only the hash from the Client ID and not the
+ entire ID. The silc_hash_client_id_compare compares the entire
+ Client ID as we want to find one specific Client ID. */
+ if (!silc_idcache_find_by_id_one_ext(id_list->clients, (void *)old_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache))
return NULL;
client = (SilcClientEntry)id_cache->context;
silc_free(client->id);
client->id = new_id;
- id_cache->id = (void *)new_id;
- /* XXX does not work correctly with the new ID Cache */
-
- /* If the old ID Cache data was the hash value of the old Client ID
- replace it with the hash of new Client ID */
- if (id_cache->data && SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
- silc_free(id_cache->data);
- id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
- memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
- }
+ /* Remove the old entry and add a new one */
+ silc_idcache_del_by_context(id_list->clients, client);
+ silc_idcache_add(id_list->clients, client->nickname, client->id,
+ client, FALSE);
SILC_LOG_DEBUG(("Replaced"));
channel_list);
if (!silc_idcache_add(id_list->channels, channel->channel_name,
- strlen(channel->channel_name),
(void *)channel->id, (void *)channel, FALSE)) {
silc_free(channel);
return NULL;
silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
SilcIDCacheEntry *ret_entry)
{
- SilcIDCacheList list = NULL;
SilcIDCacheEntry id_cache = NULL;
- SilcChannelEntry channel;
SILC_LOG_DEBUG(("Channel by name"));
- if (!silc_idcache_find_by_data(id_list->channels, name, strlen(name), &list))
- return NULL;
-
- if (!silc_idcache_list_first(list, &id_cache)) {
- silc_idcache_list_free(list);
+ if (!silc_idcache_find_by_name_one(id_list->channels, name, &id_cache))
return NULL;
- }
-
- channel = (SilcChannelEntry)id_cache->context;
if (ret_entry)
*ret_entry = id_cache;
- silc_idcache_list_free(list);
-
SILC_LOG_DEBUG(("Found"));
- return channel;
+ return id_cache->context;
}
/* Finds channel by Channel ID. */
SILC_LOG_DEBUG(("Channel ID (%s)",
silc_id_render(id, SILC_ID_CHANNEL)));
- if (!silc_idcache_find_by_id(id_list->channels, (void *)id, &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id, &id_cache))
return NULL;
channel = (SilcChannelEntry)id_cache->context;
SILC_LOG_DEBUG(("Replacing Channel ID"));
- if (!silc_idcache_find_by_id(id_list->channels, (void *)old_id, &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id,
+ &id_cache))
return NULL;
channel = (SilcChannelEntry)id_cache->context;
silc_free(channel->id);
channel->id = new_id;
- id_cache->id = (void *)new_id;
+
+ /* Remove the old entry and add a new one */
+ silc_idcache_del_by_context(id_list->channels, channel);
+ silc_idcache_add(id_list->channels, channel->channel_name, channel->id,
+ channel, FALSE);
SILC_LOG_DEBUG(("Replaced"));
silc_idcache_list_free(list);
} else {
- if (!silc_idcache_find_by_id(id_list->channels, channel_id, &id_cache))
+ if (!silc_idcache_find_by_id_one(id_list->channels, channel_id, &id_cache))
return NULL;
i = 1;
SilcServerID *new_id);
int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry);
SilcClientEntry
-silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
- uint32 nickname_len, char *username,
+silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
char *userinfo, SilcClientID *id,
SilcServerEntry router, void *connection);
int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
goto out;
client =
- silc_idlist_add_client(server->global_list, NULL, 0, NULL, NULL,
+ silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
silc_id_dup(client_id, SILC_ID_CLIENT),
sock->user_data, NULL);
if (!client) {
idata = (SilcIDListData)client;
/* Remove the old cache entry */
- silc_idcache_del_by_context(server->local_list->clients, client);
+ if (!silc_idcache_del_by_context(server->local_list->clients, client)) {
+ SILC_LOG_ERROR(("Lost client's cache entry - bad thing"));
+ silc_server_disconnect_remote(server, sock, "Server closed connection: "
+ "Unknown client");
+ return NULL;
+ }
/* Parse incoming packet */
ret = silc_buffer_unformat(buffer,
/* Add the client again to the ID cache */
silc_idcache_add(server->local_list->clients, client->nickname,
- strlen(client->nickname), client_id, client, FALSE);
+ client_id, client, FALSE);
/* Notify our router about new client on the SILC network */
if (!server->standalone)
new_server->id = server_id;
/* Add again the entry to the ID cache. */
- silc_idcache_add(server->local_list->servers, server_name,
- strlen(server_name), server_id, server, FALSE);
+ silc_idcache_add(server->local_list->servers, server_name, server_id,
+ server, FALSE);
/* Distribute the information about new server in the SILC network
to our router. If we are normal server we won't send anything
SilcSocketConnection router_sock;
SilcIDPayload idp;
SilcIdType id_type;
- unsigned char *hash = NULL;
void *id;
SILC_LOG_DEBUG(("Processing new ID"));
/* As a router we keep information of all global information in our
global list. Cell wide information however is kept in the local
- list. The client is put to global list and we will take the hash
- value of the Client ID and save it to the ID Cache system for fast
- searching in the future. */
- hash = silc_calloc(sizeof(((SilcClientID *)id)->hash),
- sizeof(unsigned char));
- memcpy(hash, ((SilcClientID *)id)->hash,
- sizeof(((SilcClientID *)id)->hash));
- entry = silc_idlist_add_client(id_list, hash,
- sizeof(((SilcClientID *)id)->hash),
- NULL, NULL, id, router, NULL);
+ list. */
+ entry = silc_idlist_add_client(id_list, NULL, NULL, NULL,
+ id, router, NULL);
entry->nickname = NULL;
entry->data.registered = TRUE;
packetdata.src_id_len = silc_id_get_len(server->id, SILC_ID_SERVER);
packetdata.src_id_type = SILC_ID_SERVER;
packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
- packetdata.dst_id_type = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ packetdata.dst_id_type = SILC_ID_CHANNEL;
packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
packetdata.src_id_len + packetdata.dst_id_len;
packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
packetdata.src_id_len = silc_id_get_len(sender, sender_type);
packetdata.src_id_type = sender_type;
packetdata.dst_id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
- packetdata.dst_id_len = SILC_ID_CHANNEL_LEN;
- packetdata.dst_id_type = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+ packetdata.dst_id_type = SILC_ID_CHANNEL;
packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
packetdata.src_id_len +
packetdata.dst_id_len));
and other information is created after we have received NEW_CLIENT
packet from client. */
client = silc_idlist_add_client(server->local_list,
- NULL, 0, NULL, NULL, NULL, NULL, sock);
+ NULL, NULL, NULL, NULL, NULL, sock);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to cache"));
silc_free(sock->user_data);
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, NULL, 0, NULL,
- NULL,
+ client = silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
silc_id_dup(client_id, SILC_ID_CLIENT),
sock->user_data, NULL);
if (!client) {
conn = silc_calloc(1, sizeof(*conn));
/* Initialize ID caches */
- conn->client_cache = silc_idcache_alloc(0, NULL);
- conn->channel_cache = silc_idcache_alloc(0, NULL);
- conn->server_cache = silc_idcache_alloc(0, NULL);
+ conn->client_cache = silc_idcache_alloc(0, SILC_ID_CLIENT, NULL);
+ conn->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
+ conn->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
conn->client = client;
conn->remote_host = strdup(hostname);
conn->remote_port = port;
connecting = TRUE;
/* Delete old ID from ID cache */
- silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT, conn->local_id);
+ if (conn->local_id) {
+ silc_idcache_del_by_context(conn->client_cache, conn->local_entry);
+ silc_free(conn->local_id);
+ }
/* Save the new ID */
- if (conn->local_id)
- silc_free(conn->local_id);
+
if (conn->local_id_data)
silc_free(conn->local_id_data);
conn->local_entry->id = conn->local_id;
/* Put it to the ID cache */
- silc_idcache_add(conn->client_cache, conn->nickname, strlen(conn->nickname),
- SILC_ID_CLIENT, conn->local_id, (void *)conn->local_entry,
- TRUE, FALSE);
+ silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id,
+ (void *)conn->local_entry, FALSE);
/* Notify application of successful connection. We do it here now that
we've received the Client ID and are allowed to send traffic. */
conn->current_channel = channel;
/* Put it to the ID cache */
- silc_idcache_add(conn->channel_cache, channel_name, strlen(channel_name),
- SILC_ID_CHANNEL, (void *)channel->id, (void *)channel,
- TRUE, FALSE);
+ silc_idcache_add(conn->channel_cache, channel_name, (void *)channel->id,
+ (void *)channel, FALSE);
return channel;
}
SilcChannelEntry channel;
SilcChannelUser chu;
- if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
- SILC_ID_CHANNEL, &list))
+ if (!silc_idcache_get_all(conn->channel_cache, &list))
return;
silc_idcache_list_first(list, &id_cache);
SilcChannelEntry channel;
SilcChannelUser chu;
- if (!silc_idcache_find_by_id(conn->channel_cache, SILC_ID_CACHE_ANY,
- SILC_ID_CHANNEL, &list))
+ if (!silc_idcache_get_all(conn->channel_cache, &list))
return;
silc_idcache_list_first(list, &id_cache);
goto out;
/* Find the channel entry from channels on this connection */
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
- SILC_ID_CHANNEL, &id_cache))
+ if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id, &id_cache))
goto out;
channel = (SilcChannelEntry)id_cache->context;
/* Find channel. */
if (!channel) {
- if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)id,
- SILC_ID_CHANNEL, &id_cache))
+ if (!silc_idcache_find_by_id_one(conn->channel_cache,
+ (void *)id, &id_cache))
goto out;
/* Get channel entry */
/* Get the channel entry */
channel = NULL;
if (silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
channel = (SilcChannelEntry)id_cache->context;
/* Get sender Client ID */
/* Get channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
if (!channel_id)
goto out;
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
silc_client_remove_from_channels(client, conn, client_entry);
/* Remove from cache */
- silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
- client_entry->id);
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
/* Get signoff message */
tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
if (!channel_id)
goto out;
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
}
/* Remove the old from cache */
- silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
- client_entry->id);
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
/* Replace old ID entry with new one on all channels. */
silc_client_replace_from_channels(client, conn, client_entry,
if (!channel_id)
goto out;
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
if (!channel_id)
goto out;
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
/* Get the channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
if (!channel_id)
goto out;
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache))
+ &id_cache))
break;
channel = (SilcChannelEntry)id_cache->context;
if (client_entry == conn->local_entry) {
if (conn->current_channel == channel)
conn->current_channel = NULL;
- silc_idcache_del_by_id(conn->channel_cache,
- SILC_ID_CHANNEL, channel->id);
+ silc_idcache_del_by_id(conn->channel_cache, channel->id);
silc_free(channel->channel_name);
silc_free(channel->id);
silc_free(channel->key);
if (client_entry != conn->local_entry) {
/* Remove client from all channels */
silc_client_remove_from_channels(client, conn, client_entry);
- silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
- client_entry->id);
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
if (client_entry->nickname)
silc_free(client_entry->nickname);
if (client_entry->server)
continue;
silc_client_remove_from_channels(client, conn, client_entry);
- silc_idcache_del_by_id(conn->client_cache, SILC_ID_CLIENT,
- client_entry->id);
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
if (client_entry->nickname)
silc_free(client_entry->nickname);
if (client_entry->server)
goto out;
/* Check whether we know this client already */
- if (!silc_idcache_find_by_id_one(conn->client_cache, remote_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)remote_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
/* Resolve the client info */
silc_client_get_client_by_id_resolve(client, conn, remote_id,
silc_client_private_message_cb,
SilcIDCacheList list;
SilcClientEntry entry;
- if (!silc_idcache_find_by_id(conn->client_cache, SILC_ID_CACHE_ANY,
- SILC_ID_CLIENT, &list))
+ if (!silc_idcache_get_all(conn->client_cache, &list))
return NULL;
if (!silc_idcache_list_count(list)) {
name = cmd->argv[1];
/* Get the Channel ID of the channel */
- if (silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+ if (silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
channel = (SilcChannelEntry)id_cache->context;
idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
}
}
/* Get the Channel ID of the channel */
- if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+ if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
COMMAND_ERROR;
goto out;
}
/* See if we have joined to the requested channel already */
- if (silc_idcache_find_by_data_one(conn->channel_cache, cmd->argv[1],
+ if (silc_idcache_find_by_name_one(conn->channel_cache, cmd->argv[1],
&id_cache)) {
cmd->client->ops->say(cmd->client, conn,
"You are talking to channel %s", cmd->argv[1]);
}
/* Get the Channel ID of the channel */
- if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+ if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
COMMAND_ERROR;
goto out;
}
/* Get the Channel ID of the channel */
- if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+ if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
cmd->client->ops->say(cmd->client, conn, "You are not on that channel");
COMMAND_ERROR;
goto out;
conn->current_channel = NULL;
- silc_idcache_del_by_id(conn->channel_cache, SILC_ID_CHANNEL, channel->id);
+ silc_idcache_del_by_id(conn->channel_cache, channel->id);
silc_free(channel->channel_name);
silc_free(channel->id);
silc_free(channel->key);
}
/* Get the Channel ID of the channel */
- if (!silc_idcache_find_by_data_one(conn->channel_cache, name, &id_cache)) {
+ if (!silc_idcache_find_by_name_one(conn->channel_cache, name, &id_cache)) {
/* XXX should resolve the channel ID; LIST command */
cmd->client->ops->say(cmd->client, conn,
"You are not on that channel", name);
SILC_GET32_MSB(idle, tmp);
/* Check if we have this client cached already. */
- if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
SILC_LOG_DEBUG(("Adding new client entry"));
client_entry = silc_calloc(1, sizeof(*client_entry));
/* Add client to cache */
silc_idcache_add(conn->client_cache, client_entry->nickname,
- strlen(client_entry->nickname),
- SILC_ID_CLIENT, client_id, (void *)client_entry,
- TRUE, FALSE);
+ client_id, (void *)client_entry, FALSE);
} else {
client_entry = (SilcClientEntry)id_cache->context;
if (client_entry->nickname)
if (realname)
client_entry->realname = strdup(realname);
- id_cache->data = client_entry->nickname;
- id_cache->data_len = strlen(client_entry->nickname);
- silc_idcache_sort_by_data(conn->client_cache);
-
+ /* Remove the old cache entry and create a new one */
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
+ silc_idcache_add(conn->client_cache, client_entry->nickname,
+ client_entry->id, client_entry, FALSE);
silc_free(client_id);
}
}
/* Get the client entry, if exists */
- if (silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache))
+ if (silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache))
client_entry = (SilcClientEntry)id_cache->context;
silc_free(client_id);
username = silc_argument_get_arg_type(cmd->args, 4, &len);
/* Check if we have this client cached already. */
- if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
SILC_LOG_DEBUG(("Adding new client entry"));
client_entry = silc_calloc(1, sizeof(*client_entry));
/* Add client to cache */
silc_idcache_add(conn->client_cache, client_entry->nickname,
- strlen(client_entry->nickname),
- SILC_ID_CLIENT, client_id, (void *)client_entry,
- TRUE, FALSE);
+ client_id, (void *)client_entry, FALSE);
} else {
client_entry = (SilcClientEntry)id_cache->context;
if (client_entry->nickname)
if (username)
client_entry->username = strdup(username);
- id_cache->data = client_entry->nickname;
- id_cache->data_len = strlen(client_entry->nickname);
- silc_idcache_sort_by_data(conn->client_cache);
-
+ /* Remove the old cache entry and create a new one */
+ silc_idcache_del_by_context(conn->client_cache, client_entry);
+ silc_idcache_add(conn->client_cache, client_entry->nickname,
+ client_entry->id, client_entry, FALSE);
silc_free(client_id);
}
/* Get the channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache)) {
+ &id_cache)) {
silc_free(channel_id);
COMMAND_REPLY_ERROR;
goto out;
/* Get the channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache)) {
+ &id_cache)) {
silc_free(channel_id);
COMMAND_REPLY_ERROR;
goto out;
SILC_GET32_MSB(mode, client_mode_list->data);
/* Check if we have this client cached already. */
- if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
/* No, we don't have it, add entry for it. */
client_entry = silc_calloc(1, sizeof(*client_entry));
client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
- silc_idcache_add(conn->client_cache, NULL, 0, SILC_ID_CLIENT,
- client_entry->id, (void *)client_entry, FALSE, FALSE);
+ silc_idcache_add(conn->client_cache, NULL, client_entry->id,
+ (void *)client_entry, FALSE);
} else {
/* Yes, we have it already */
client_entry = (SilcClientEntry)id_cache->context;
}
/* Get client entry */
- if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
COMMAND_REPLY_ERROR;
goto out;
}
/* Get the channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache)) {
+ &id_cache)) {
silc_free(channel_id);
COMMAND_REPLY_ERROR;
goto out;
/* Get channel entry */
if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
- SILC_ID_CHANNEL, &id_cache)) {
+ &id_cache)) {
COMMAND_REPLY_ERROR;
goto out;
}
SILC_GET32_MSB(mode, client_mode_list->data);
/* Check if we have this client cached already. */
- if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
/* No we don't have it, query it from the server. Assemble argument
table that will be sent fr the IDENTIFY command later. */
res_argv = silc_realloc(res_argv, sizeof(*res_argv) *
if (id_type == SILC_ID_CLIENT) {
client_id = silc_id_payload_get_id(idp);
- if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache))
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache))
goto out;
client_entry = (SilcClientEntry)id_cache->context;
int i = 0;
/* Find ID from cache */
- if (!silc_idcache_find_by_data_loose(conn->client_cache, nickname, &list))
+ if (!silc_idcache_find_by_name(conn->client_cache, nickname,
+ &list))
return NULL;
if (!silc_idcache_list_count(list)) {
continue;
/* Get the client entry */
- if (silc_idcache_find_by_id_one(i->conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache)) {
+ if (silc_idcache_find_by_id_one_ext(i->conn->client_cache,
+ (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache)) {
clients = silc_realloc(clients, sizeof(*clients) *
(clients_count + 1));
clients[clients_count] = (SilcClientEntry)id_cache->context;
/* Check if we have this client cached already. */
id_cache = NULL;
- silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
- SILC_ID_CLIENT, &id_cache);
+ silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache);
/* If we don't have the entry or it has incomplete info, then resolve
it from the server. */
SilcClientEntry entry = NULL;
/* Find ID from cache */
- if (!silc_idcache_find_by_data_loose(conn->client_cache, nickname, &list)) {
+ if (!silc_idcache_find_by_name(conn->client_cache, nickname,
+ &list)) {
identify:
if (query) {
silc_id_render(client_id, SILC_ID_CLIENT)));
/* Find ID from cache */
- if (!silc_idcache_find_by_id_one(conn->client_cache, client_id,
- SILC_ID_CLIENT, &id_cache))
+ if (!silc_idcache_find_by_id_one_ext(conn->client_cache, (void *)client_id,
+ NULL, NULL,
+ silc_hash_client_id_compare, NULL,
+ &id_cache))
return NULL;
SILC_LOG_DEBUG(("Found"));
SilcIDCacheEntry id_cache;
SilcChannelEntry entry;
- if (!silc_idcache_find_by_data_one(conn->channel_cache, channel, &id_cache))
+ if (!silc_idcache_find_by_name_one(conn->channel_cache, channel,
+ &id_cache))
return NULL;
entry = (SilcChannelEntry)id_cache->context;
SILC_ID_CHANNEL_COMPARE(id1, id2))
/* Compare nickname hash from Client ID */
-#define SILC_ID_COMPARE_HASH(id, _hash) \
- memcmp(id->hash, _hash, CLIENTID_HASH_LEN)
+#define SILC_ID_COMPARE_HASH(id1, id2) \
+ (!memcmp((id1)->hash, (id2)->hash, CLIENTID_HASH_LEN))
/* Prototypes */
unsigned char *silc_id_id2str(void *id, SilcIdType type);
Hash table using the ID as the key.
- SilcHashTable data_table
+ SilcHashTable name_table
- Hash table using the data as the key.
+ Hash table using the name as the key.
SilcHashTable context_table
*/
struct SilcIDCacheStruct {
SilcHashTable id_table;
- SilcHashTable data_table;
+ SilcHashTable name_table;
SilcHashTable context_table;
SilcIDCacheDestructor destructor;
SilcIdType type;
silc_hash_id_compare,
(void *)(uint32)id_type,
silc_idcache_destructor, NULL);
- cache->data_table = silc_hash_table_alloc(count, silc_hash_data, NULL,
- silc_hash_data_compare, NULL,
+ cache->name_table = silc_hash_table_alloc(count, silc_hash_string, NULL,
+ silc_hash_string_compare, NULL,
NULL, NULL);
cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL,
NULL, NULL, NULL, NULL);
{
if (cache) {
silc_hash_table_free(cache->id_table);
- silc_hash_table_free(cache->data_table);
+ silc_hash_table_free(cache->name_table);
silc_hash_table_free(cache->context_table);
silc_free(cache);
}
/* Add new entry to the cache. */
-bool silc_idcache_add(SilcIDCache cache, unsigned char *data,
- uint32 data_len, void *id, void *context, int expire)
+bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
+ void *context, int expire)
{
SilcIDCacheEntry c;
uint32 curtime = time(NULL);
SILC_LOG_DEBUG(("Adding cache entry"));
- /* See if entry with this ID already exists. */
- if (silc_hash_table_find(cache->id_table, id, NULL, NULL))
- return FALSE;
-
/* Allocate new cache entry */
c = silc_calloc(1, sizeof(*c));
- c->data = data;
- c->data_len = data_len;
c->id = id;
+ c->name = name;
c->expire = (expire ? (curtime + SILC_ID_CACHE_EXPIRE) : 0);
c->context = context;
/* Add the new entry to the hash tables */
- silc_hash_table_add(cache->id_table, id, c);
- if (data)
- silc_hash_table_add_ext(cache->data_table, data, c,
- silc_hash_data, (void *)data_len);
+ if (id)
+ silc_hash_table_add(cache->id_table, id, c);
+ if (name)
+ silc_hash_table_add(cache->name_table, name, c);
if (context)
silc_hash_table_add(cache->context_table, context, c);
if ((silc_hash_table_count(cache->id_table) / 2) >
silc_hash_table_size(cache->id_table)) {
silc_hash_table_rehash(cache->id_table, 0);
- silc_hash_table_rehash(cache->data_table, 0);
+ silc_hash_table_rehash(cache->name_table, 0);
silc_hash_table_rehash(cache->context_table, 0);
}
bool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old)
{
- bool ret;
+ bool ret = FALSE;
+
+ SILC_LOG_DEBUG(("Deleting cache entry"));
- ret = silc_hash_table_del_by_context_ext(cache->data_table, old->data, old,
- silc_hash_data,
- (void *)old->data_len,
- silc_hash_data_compare,
- (void *)old->data_len);
- ret = silc_hash_table_del(cache->context_table, old->context);
- ret = silc_hash_table_del(cache->id_table, old->id);
+ if (old->name)
+ ret = silc_hash_table_del_by_context(cache->name_table, old->name, old);
+ if (old->context)
+ ret = silc_hash_table_del(cache->context_table, old->context);
+ if (old->id)
+ ret = silc_hash_table_del(cache->id_table, old->id);
return ret;
}
return silc_idcache_del(cache, c);
}
+/* Same as above but with specific hash and comparison functions. If the
+ functions are NULL then default values are used. */
+
+bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
+ SilcHashFunction hash,
+ void *hash_context,
+ SilcHashCompare compare,
+ void *compare_context)
+{
+ SilcIDCacheEntry c;
+ bool ret = FALSE;
+
+ SILC_LOG_DEBUG(("Deleting cache entry"));
+
+ if (!silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)&c,
+ hash, hash_context, compare,
+ compare_context))
+ return FALSE;
+
+ if (c->name)
+ ret = silc_hash_table_del_by_context(cache->name_table, c->name, c);
+ if (c->context)
+ ret = silc_hash_table_del(cache->context_table, c->context);
+ if (c->id)
+ ret = silc_hash_table_del_ext(cache->id_table, c->id, hash,
+ hash_context, compare, compare_context);
+
+ return ret;
+}
+
/* Deletes ID cache entry by context. */
bool silc_idcache_del_by_context(SilcIDCache cache, void *context)
{
SilcIDCacheEntry c;
+ bool ret = FALSE;
+
+ SILC_LOG_DEBUG(("Deleting cache entry"));
if (!silc_hash_table_find(cache->context_table, context, NULL, (void *)&c))
return FALSE;
- return silc_idcache_del(cache, c);
+ if (c->name)
+ ret = silc_hash_table_del_by_context(cache->name_table, c->name, c);
+ if (c->context)
+ ret = silc_hash_table_del(cache->context_table, c->context);
+ if (c->id)
+ ret = silc_hash_table_del_by_context(cache->id_table, c->id, c);
+
+ return ret;
}
/* Deletes all ID entries from cache. Free's memory as well. */
bool silc_idcache_del_all(SilcIDCache cache)
{
silc_hash_table_free(cache->id_table);
- silc_hash_table_free(cache->data_table);
+ silc_hash_table_free(cache->name_table);
silc_hash_table_free(cache->context_table);
return TRUE;
return TRUE;
}
-/* Find ID Cache entry by ID. */
+/* Find ID Cache entry by ID. May return multiple entries. */
bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
- SilcIDCacheEntry *ret)
+ SilcIDCacheList *ret)
+{
+ SilcIDCacheList list;
+
+ list = silc_idcache_list_alloc();
+
+ if (!ret)
+ return TRUE;
+
+ silc_hash_table_find_foreach(cache->id_table, id,
+ silc_idcache_get_all_foreach, list);
+
+ if (silc_idcache_list_count(list) == 0) {
+ silc_idcache_list_free(list);
+ return FALSE;
+ }
+
+ *ret = list;
+
+ return TRUE;
+}
+
+/* Find specific ID with specific hash function and comparison functions.
+ If `hash' is NULL then the default hash funtion is used and if `compare'
+ is NULL default comparison function is used. */
+
+bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
+ SilcHashFunction hash,
+ void *hash_context,
+ SilcHashCompare compare,
+ void *compare_context,
+ SilcIDCacheEntry *ret)
+{
+ return silc_hash_table_find_ext(cache->id_table, id, NULL, (void *)ret,
+ hash, hash_context, compare,
+ compare_context);
+}
+
+/* Find one specific ID entry. */
+
+bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
+ SilcIDCacheEntry *ret)
{
return silc_hash_table_find(cache->id_table, id, NULL, (void *)ret);
}
(void *)ret);
}
-/* Find ID Cache entry by data. The data maybe anything that must
- match exactly. Returns list of cache entries. */
+/* Find ID Cache entry by name. Returns list of cache entries. */
-bool silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
- unsigned int data_len, SilcIDCacheList *ret)
+bool silc_idcache_find_by_name(SilcIDCache cache, char *name,
+ SilcIDCacheList *ret)
{
SilcIDCacheList list;
if (!ret)
return TRUE;
- silc_hash_table_find_foreach_ext(cache->data_table, data,
- silc_hash_data, (void *)data_len,
- silc_hash_data_compare, (void *)data_len,
- silc_idcache_get_all_foreach, list);
+ silc_hash_table_find_foreach(cache->name_table, name,
+ silc_idcache_get_all_foreach, list);
if (silc_idcache_list_count(list) == 0) {
silc_idcache_list_free(list);
return TRUE;
}
-/* Find ID Cache entry by data. The data maybe anything that must
- match exactly. Returns one cache entry. */
+/* Find ID Cache entry by name. Returns one cache entry. */
-bool silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
- unsigned int data_len,
+bool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
SilcIDCacheEntry *ret)
{
- SilcIDCacheEntry c;
-
- if (!silc_hash_table_find_ext(cache->data_table, data, NULL, (void *)&c,
- silc_hash_data, (void *)data_len,
- silc_hash_data_compare, (void *)data_len))
+ if (!silc_hash_table_find(cache->name_table, name, NULL, (void *)ret))
return FALSE;
- if (ret)
- *ret = c;
-
return TRUE;
}
This is one entry in the SILC ID Cache system. Contents of this is
allocated outside the ID cache system, however, all the fields are
filled with ID cache utility functions. The ID cache system does not
- allocate any of these fields nor free them. The system assumes that
- the type of the ID in a specific ID Cache context are of the same
- type. One should not mix different types of ID's (eg. Client ID and
- Server ID) to the same ID Cache context.
-
- unsigned char *data
- uint32 data_len;
-
- The data that is usually used to find the data from the cache.
- For example for Client ID's this is nickname.
+ allocate any of these fields nor free them.
void *id
The actual ID.
+ char name
+
+ A name associated with the ID.
+
uint32 expire
Time when this cache entry expires. This is normal time() value
*/
typedef struct {
- unsigned char *data;
- uint32 data_len;
void *id;
+ char *name;
uint32 expire;
void *context;
} *SilcIDCacheEntry;
SilcIDCache silc_idcache_alloc(uint32 count, SilcIdType id_type,
SilcIDCacheDestructor destructor);
void silc_idcache_free(SilcIDCache cache);
-bool silc_idcache_add(SilcIDCache cache, unsigned char *data,
- uint32 data_len, void *id, void *context, int expire);
+bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
+ void *context, int expire);
bool silc_idcache_del(SilcIDCache cache, SilcIDCacheEntry old);
bool silc_idcache_del_by_id(SilcIDCache cache, void *id);
+bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
+ SilcHashFunction hash,
+ void *hash_context,
+ SilcHashCompare compare,
+ void *compare_context);
bool silc_idcache_del_by_context(SilcIDCache cache, void *context);
bool silc_idcache_del_all(SilcIDCache cache);
bool silc_idcache_purge(SilcIDCache cache);
bool silc_idcache_purge_by_context(SilcIDCache cache, void *context);
bool silc_idcache_get_all(SilcIDCache cache, SilcIDCacheList *ret);
bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
- SilcIDCacheEntry *ret);
+ SilcIDCacheList *ret);
+bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
+ SilcIDCacheEntry *ret);
+bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
+ SilcHashFunction hash,
+ void *hash_context,
+ SilcHashCompare compare,
+ void *compare_context,
+ SilcIDCacheEntry *ret);
bool silc_idcache_find_by_context(SilcIDCache cache, void *context,
SilcIDCacheEntry *ret);
-bool silc_idcache_find_by_data(SilcIDCache cache, unsigned char *data,
- unsigned int data_len, SilcIDCacheList *ret);
-bool silc_idcache_find_by_data_one(SilcIDCache cache, unsigned char *data,
- unsigned int data_len,
+bool silc_idcache_find_by_name(SilcIDCache cache, char *name,
+ SilcIDCacheList *ret);
+bool silc_idcache_find_by_name_one(SilcIDCache cache, char *name,
SilcIDCacheEntry *ret);
int silc_idcache_list_count(SilcIDCacheList list);
bool silc_idcache_list_first(SilcIDCacheList list, SilcIDCacheEntry *ret);
#include "silcincludes.h"
#include "silchashtable.h"
+/* Define to 1 if you want hash table debug enabled */
+#define SILC_HASH_TABLE_DEBUG 0
+
+#if SILC_HASH_TABLE_DEBUG == 1
+#define SILC_HT_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
+#else
+#define SILC_HT_DEBUG(fmt)
+#endif
+
/* Default size of the hash table (index to prime table) */
#define SILC_HASH_TABLE_SIZE 3
for (i = 0; i < sizeof(primesize); i++)
if (primesize[i] >= size) {
*index = i;
+ SILC_HT_DEBUG(("sizeof of the hash table is %d", primesize[*index]));
return primesize[i];
}
*index = i - 1;
+ SILC_HT_DEBUG(("sizeof of the hash table is %d", primesize[*index]));
return primesize[i - 1];
}
void *compare_user_context)
{
SilcHashTableEntry *entry, prev = NULL;
+ uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+ SILC_HT_DEBUG(("index %d key %p", i, key));
- entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+ entry = &ht->table[i];
if (compare) {
while (*entry && !compare((*entry)->key, key, compare_user_context)) {
prev = *entry;
void *compare_user_context)
{
SilcHashTableEntry *entry, prev = NULL;
+ uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
- entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+ SILC_HT_DEBUG(("index %d key %p context %p", i, key, context));
+
+ entry = &ht->table[i];
if (ht->compare) {
- while (*entry && !compare((*entry)->key, key, compare_user_context) &&
- (*entry)->context != context) {
+ while (*entry) {
+ if (compare((*entry)->key, key, compare_user_context) &&
+ (*entry)->context == context)
+ break;
prev = *entry;
entry = &(*entry)->next;
}
} else {
- while (*entry && (*entry)->key != key && (*entry)->context != context) {
+ while (*entry) {
+ if ((*entry)->key == key && (*entry)->context == context)
+ break;
prev = *entry;
entry = &(*entry)->next;
}
void *compare_user_context)
{
SilcHashTableEntry *entry;
+ uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
- entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+ SILC_HT_DEBUG(("index %d key %p", i, key));
+
+ entry = &ht->table[i];
if (compare) {
while (*entry && !compare((*entry)->key, key, compare_user_context))
entry = &(*entry)->next;
void *foreach_user_context)
{
SilcHashTableEntry *entry;
+ uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+ SILC_HT_DEBUG(("index %d key %p", i, key));
- entry = &ht->table[SILC_HASH_TABLE_HASH_F(hash, hash_user_context)];
+ entry = &ht->table[i];
if (compare) {
while (*entry) {
if (compare((*entry)->key, key, compare_user_context))
void *hash_user_context)
{
SilcHashTableEntry *entry;
- uint32 index = (hash ? SILC_HASH_TABLE_HASH :
- SILC_HASH_TABLE_HASH_F(hash, hash_user_context));
+ uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+ SILC_HT_DEBUG(("index %d key %p", i, key));
- entry = &ht->table[index];
+ entry = &ht->table[i];
if (*entry) {
/* The entry exists already. We have a collision, add it to the
list to avoid collision. */
tmp = tmp->next;
}
+ SILC_HT_DEBUG(("Collision; adding new key to list"));
+
e->next = silc_calloc(1, sizeof(*e->next));
e->next->key = key;
e->next->context = context;
ht->entry_count++;
} else {
/* New key */
+ SILC_HT_DEBUG(("New key"));
*entry = silc_calloc(1, sizeof(**entry));
(*entry)->key = key;
(*entry)->context = context;
void *hash_user_context)
{
SilcHashTableEntry *entry;
- uint32 index = (hash ? SILC_HASH_TABLE_HASH :
- SILC_HASH_TABLE_HASH_F(hash, hash_user_context));
+ uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+
+ SILC_HT_DEBUG(("index %d key %p", i, key));
- entry = &ht->table[index];
+ entry = &ht->table[i];
if (*entry) {
/* The entry exists already. We have a collision, replace the old
key and context. */
void silc_hash_table_add(SilcHashTable ht, void *key, void *context)
{
- silc_hash_table_add_internal(ht, key, context, NULL, NULL);
+ silc_hash_table_add_internal(ht, key, context, ht->hash,
+ ht->hash_user_context);
}
/* Same as above but with specific hash function and user context. */
void silc_hash_table_replace(SilcHashTable ht, void *key, void *context)
{
- silc_hash_table_replace_internal(ht, key, context, NULL, NULL);
+ silc_hash_table_replace_internal(ht, key, context, ht->hash,
+ ht->hash_user_context);
}
/* Same as above but with specific hash function. */
/* Remove old table */
silc_free(table);
}
+
+/* Same as above but with specific hash function. */
+
+void silc_hash_table_rehash_ext(SilcHashTable ht, uint32 new_size,
+ SilcHashFunction hash,
+ void *hash_user_context)
+{
+ int i;
+ SilcHashTableEntry *table, e, tmp;
+ uint32 table_size, size_index;
+
+ SILC_HT_DEBUG(("Rehashing"));
+
+ /* Take old hash table */
+ table = ht->table;
+ table_size = ht->table_size;
+
+ /* Allocate new table */
+ ht->table = silc_calloc(new_size ? silc_hash_table_primesize(new_size,
+ &size_index) :
+ silc_hash_table_primesize(ht->entry_count,
+ &size_index),
+ sizeof(*ht->table));
+ ht->table_size = size_index;
+
+ /* Rehash */
+ for (i = 0; i < primesize[table_size]; i++) {
+ e = table[i];
+ while (e) {
+ silc_hash_table_add_ext(ht, e->key, e->context, hash,
+ hash_user_context);
+ tmp = e;
+ e = e->next;
+
+ /* Remove old entry */
+ silc_free(tmp);
+ }
+ }
+
+ /* Remove old table */
+ silc_free(table);
+}
void *compare_user_context,
SilcHashForeach foreach,
void *foreach_user_context);
+void silc_hash_table_rehash_ext(SilcHashTable ht, uint32 new_size,
+ SilcHashFunction hash,
+ void *hash_user_context);
#endif
return realname;
}
-/* Basic has function to hash strings. May be used with the SilcHashTable. */
+/* Basic has function to hash strings. May be used with the SilcHashTable.
+ Note that this lowers the characters of the string (with tolower()) so
+ this is used usually with nicknames, channel and server names to provide
+ case insensitive keys. */
uint32 silc_hash_string(void *key, void *user_context)
{
uint32 h = 0, g;
while (*s != '\0') {
- h = (h << 4) + toupper(*s);
+ h = (h << 4) + tolower(*s);
if ((g = h & 0xf0000000)) {
h = h ^ (g >> 24);
h = h ^ g;
{
SilcIdType id_type = (SilcIdType)(uint32)user_context;
uint32 h = 0;
+ int i;
switch (id_type) {
case SILC_ID_CLIENT:
{
SilcClientID *id = (SilcClientID *)key;
- int i;
- uint32 h;
-
- h = id->rnd;
- for (i = 0; i < sizeof(id->hash); i++)
- h ^= id->hash[i];
- for (i = 0; i < id->ip.data_len; i++)
- h ^= id->ip.data[i];
-
+ uint32 g;
+
+ /* 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. */
+
+ for (i = 0; i < sizeof(id->hash); i++) {
+ h = (h << 4) + id->hash[i];
+ if ((g = h & 0xf0000000)) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+
return h;
}
break;
case SILC_ID_SERVER:
{
SilcServerID *id = (SilcServerID *)key;
- int i;
- uint32 h;
h = id->port * id->rnd;
for (i = 0; i < id->ip.data_len; i++)
case SILC_ID_CHANNEL:
{
SilcChannelID *id = (SilcChannelID *)key;
- int i;
- uint32 h;
h = id->port * id->rnd;
for (i = 0; i < id->ip.data_len; i++)
return h;
}
-/* Compares two ID's. May be used as SilcHashTable comparison function. */
+/* Compares two strings. May be used as SilcHashTable comparison function. */
+
+bool silc_hash_string_compare(void *key1, void *key2, void *user_context)
+{
+ return !strcasecmp((char *)key1, (char *)key2);
+}
+
+/* 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. */
bool silc_hash_id_compare(void *key1, void *key2, void *user_context)
{
SilcIdType id_type = (SilcIdType)(uint32)user_context;
- return SILC_ID_COMPARE_TYPE(key1, key2, id_type);
+ return (id_type == SILC_ID_CLIENT ?
+ SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) :
+ SILC_ID_COMPARE_TYPE(key1, key2, id_type));
+}
+
+/* Compare two Client ID's entirely and not just the hash from the ID. */
+
+bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context)
+{
+ return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT);
}
/* Compares binary data. May be used as SilcHashTable comparison function. */
uint32 silc_hash_ptr(void *key, void *user_context);
uint32 silc_hash_id(void *key, void *user_context);
uint32 silc_hash_data(void *key, void *user_context);
+bool silc_hash_string_compare(void *key1, void *key2, void *user_context);
bool silc_hash_id_compare(void *key1, void *key2, void *user_context);
+bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context);
bool silc_hash_data_compare(void *key1, void *key2, void *user_context);
#endif