+/* Finds server by Server ID */
+
+SilcServerEntry
+silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
+ SilcBool registered, SilcIDCacheEntry *ret_entry)
+{
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server;
+
+ if (!id)
+ return NULL;
+
+ SILC_LOG_DEBUG(("Server ID (%s)",
+ silc_id_render(id, SILC_ID_SERVER)));
+
+ if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id, &id_cache))
+ return NULL;
+
+ server = (SilcServerEntry)id_cache->context;
+
+ if (server && registered &&
+ !(server->data.status & SILC_IDLIST_STATUS_REGISTERED))
+ return NULL;
+
+ if (ret_entry)
+ *ret_entry = id_cache;
+
+ SILC_LOG_DEBUG(("Found"));
+
+ return server;
+}
+
+/* Find server by name. The 'name' must be normalized already. */
+
+SilcServerEntry
+silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
+ SilcBool registered,
+ SilcIDCacheEntry *ret_entry)
+{
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server;
+
+ SILC_LOG_DEBUG(("Server by name `%s'", name));
+
+ if (!silc_idcache_find_by_name_one(id_list->servers, name, &id_cache))
+ return NULL;
+
+ server = (SilcServerEntry)id_cache->context;
+
+ if (server && registered &&
+ !(server->data.status & SILC_IDLIST_STATUS_REGISTERED))
+ return NULL;
+
+ if (ret_entry)
+ *ret_entry = id_cache;
+
+ SILC_LOG_DEBUG(("Found"));
+
+ return server;
+}
+
+/* Find server by connection parameters, hostname and port */
+
+SilcServerEntry
+silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
+ int port, SilcBool registered,
+ SilcIDCacheEntry *ret_entry)
+{
+ SilcList list;
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server = NULL;
+ SilcPacketStream sock;
+ const char *host = NULL, *ip = NULL;
+
+ SILC_LOG_DEBUG(("Server by hostname %s and port %d", hostname, port));
+
+ if (!silc_idcache_get_all(id_list->servers, &list))
+ return NULL;
+
+ silc_list_start(list);
+ while ((id_cache = silc_list_get(list))) {
+ server = id_cache->context;
+ sock = server->connection;
+
+ if (sock && silc_socket_stream_get_info(
+ silc_packet_stream_get_stream(sock),
+ NULL, &host, &ip, NULL)) {
+ if (((host && !strcasecmp(host, hostname)) ||
+ (ip && !strcasecmp(ip, hostname))) &&
+ server->id->port == SILC_SWAB_16(port))
+ break;
+ }
+
+ id_cache = NULL;
+ server = NULL;
+ }
+
+ if (server && registered &&
+ !(server->data.status & SILC_IDLIST_STATUS_REGISTERED))
+ return NULL;
+
+ if (ret_entry)
+ *ret_entry = id_cache;
+
+ SILC_LOG_DEBUG(("Found"));
+
+ return server;
+}
+
+/* Replaces old Server ID with new one */
+
+SilcServerEntry
+silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
+ SilcServerID *new_id)
+{
+ SilcIDCacheEntry id_cache = NULL;
+ SilcServerEntry server;
+ char *name;
+
+ if (!old_id || !new_id)
+ return NULL;
+
+ SILC_LOG_DEBUG(("Replacing Server ID"));
+
+ if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id, &id_cache))
+ return NULL;
+
+ server = (SilcServerEntry)id_cache->context;
+ name = strdup(id_cache->name);
+
+ /* Remove the old entry and add a new one */
+
+ silc_idcache_del_by_id(id_list->servers, (void *)server->id, NULL);
+ *server->id = *new_id;
+ silc_idcache_add(id_list->servers, name, server->id, server);
+
+ SILC_LOG_DEBUG(("Found"));
+
+ return server;
+}
+
+/* Removes and free's server entry from ID list */
+
+int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
+{
+ if (entry) {
+ /* Remove from cache */
+ if (!silc_idcache_del_by_context(id_list->servers, entry, NULL)) {
+ SILC_LOG_DEBUG(("Unknown server, did not delete"));
+ return FALSE;
+ }
+
+ SILC_LOG_DEBUG(("Deleting server %s id %s", entry->server_name ?
+ entry->server_name : "",
+ entry->id ?
+ silc_id_render(entry->id, SILC_ID_SERVER) : ""));
+
+ /* Free data */
+ silc_free(entry->server_name);
+ silc_free(entry->id);
+ silc_free(entry->server_info);
+
+ memset(entry, 'F', sizeof(*entry));
+ silc_free(entry);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* ID Cache destructor */
+
+void silc_idlist_server_destructor(SilcIDCache cache,
+ SilcIDCacheEntry entry,
+ void *dest_context,
+ void *app_context)
+{
+ silc_free(entry->name);
+}
+