return server;
}
+/* Find server by name */
+
+SilcServerEntry
+silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
+ SilcIDCacheEntry *ret_entry)
+{
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server;
+
+ SILC_LOG_DEBUG(("Server by name `%s'", name));
+
+ if (!silc_idcache_find_by_data_one(id_list->servers, name, &id_cache))
+ return NULL;
+
+ server = (SilcServerEntry)id_cache->context;
+
+ if (ret_entry)
+ *ret_entry = id_cache;
+
+ return server;
+}
+
+/* Find server by connection parameters, hostname and port */
+
+SilcServerEntry
+silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
+ int port, SilcIDCacheEntry *ret_entry)
+{
+ SilcIDCacheList list = NULL;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server = NULL;
+ SilcSocketConnection sock;
+
+ SILC_LOG_DEBUG(("Server by hostname %s and port %d", hostname, port));
+
+ if (!silc_idcache_find_by_id(id_list->servers, SILC_ID_CACHE_ANY,
+ SILC_ID_SERVER, &list))
+ return NULL;
+
+ if (!silc_idcache_list_first(list, &id_cache)) {
+ silc_idcache_list_free(list);
+ return NULL;
+ }
+
+ while (id_cache) {
+ server = (SilcServerEntry)id_cache->context;
+ sock = (SilcSocketConnection)server->connection;
+
+ if (sock && (!strcmp(sock->hostname, hostname) ||
+ !strcmp(sock->ip, hostname)) && sock->port == port)
+ break;
+
+ id_cache = NULL;
+ server = NULL;
+
+ if (!silc_idcache_list_next(list, &id_cache))
+ break;
+ }
+
+ silc_idcache_list_free(list);
+
+ if (ret_entry)
+ *ret_entry = id_cache;
+
+ SILC_LOG_DEBUG(("Found"));
+
+ return server;
+}
+
/* Replaces old Server ID with new one */
SilcServerEntry
silc_free(entry->server_name);
if (entry->id)
silc_free(entry->id);
+
+ memset(entry, 'F', sizeof(*entry));
+ silc_free(entry);
}
}
/* Add new client entry. This adds the client entry to ID cache system
and returns the allocated client entry or NULL on error. This is
- called when new client connection is accepted to the server. */
+ called when new client connection is accepted to the server. If The
+ `router' is provided then the all server routines assume that the client
+ is not directly connected local client but it has router set and is
+ remote. If this is the case then `connection' must be NULL. If, on the
+ other hand, the `connection' is provided then the client is assumed
+ to be directly connected local client and `router' must be NULL. */
SilcClientEntry
silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
/* Free client entry. This free's everything and removes the entry
from ID cache. Call silc_idlist_del_data before calling this one. */
-void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
+int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
{
if (entry) {
/* Remove from cache */
if (entry->id)
- silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
- (void *)entry->id);
+ if (!silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
+ (void *)entry->id))
+ return FALSE;
/* Free data */
if (entry->nickname)
silc_free(entry->userinfo);
if (entry->id)
silc_free(entry->id);
+
+ memset(entry, 'F', sizeof(*entry));
+ silc_free(entry);
+
+ return TRUE;
}
+
+ return FALSE;
}
/* Returns all clients matching requested nickname. Number of clients is
silc_idcache_sort_by_data(id_list->clients);
}
+ SILC_LOG_DEBUG(("Replaced"));
+
return client;
}
/* Free channel entry. This free's everything. */
-void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
+int 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,
- (void *)entry->id);
+ if (!silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
+ (void *)entry->id))
+ return FALSE;
/* Free data */
if (entry->channel_name)
memset(entry->key, 0, entry->key_len / 8);
silc_free(entry->key);
}
- memset(entry->iv, 0, sizeof(entry->iv));
-
+
+ /* Free all data, free also any reference from the client's channel
+ list since they share the same memory. */
silc_list_start(entry->user_list);
while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
+ silc_list_del(chl->client->channels, chl);
silc_list_del(entry->user_list, chl);
silc_free(chl);
}
+
+ memset(entry, 'F', sizeof(*entry));
+ silc_free(entry);
+ return TRUE;
}
+
+ return FALSE;
}
/* Finds channel by channel name. Channel names are unique and they
return channel;
}
+
+/* Replaces old Channel ID with new one. This is done when router forces
+ normal server to change Channel ID. */
+
+SilcChannelEntry
+silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
+ SilcChannelID *new_id)
+{
+ SilcIDCacheEntry id_cache = NULL;
+ SilcChannelEntry channel;
+
+ if (!old_id || !new_id)
+ return NULL;
+
+ SILC_LOG_DEBUG(("Replacing Channel ID"));
+
+ if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id,
+ SILC_ID_CHANNEL, &id_cache))
+ return NULL;
+
+ channel = (SilcChannelEntry)id_cache->context;
+ silc_free(channel->id);
+ channel->id = new_id;
+ id_cache->id = (void *)new_id;
+
+ return channel;
+}