+/*********************** Server Resolving from Server ***********************/
+
+/* Resolving context */
+typedef struct {
+ SilcDList servers;
+ SilcGetServerCallback completion;
+ void *context;
+} *SilcClientGetServerInternal;
+
+/* Resolving command callback */
+
+static SilcBool silc_client_get_server_cb(SilcClient client,
+ SilcClientConnection conn,
+ SilcCommand command,
+ SilcStatus status,
+ SilcStatus error,
+ void *context,
+ va_list ap)
+{
+ SilcClientGetServerInternal i = context;
+ SilcServerEntry server;
+
+ if (error != SILC_STATUS_OK) {
+ SILC_LOG_DEBUG(("Resolving failed: %s", silc_get_status_message(error)));
+ if (i->completion)
+ i->completion(client, conn, error, NULL, i->context);
+ goto out;
+ }
+
+ /* Add the returned servers to list */
+ if (i->completion) {
+ server = va_arg(ap, SilcServerEntry);
+ silc_client_ref_server(client, conn, server);
+ silc_dlist_add(i->servers, server);
+ server->internal.resolve_cmd_ident = 0;
+ }
+
+ if (status == SILC_STATUS_OK || status == SILC_STATUS_LIST_END) {
+ /* Deliver the servers to the caller */
+ if (i->completion) {
+ SILC_LOG_DEBUG(("Resolved %d servers", silc_dlist_count(i->servers)));
+ silc_dlist_start(i->servers);
+ i->completion(client, conn, SILC_STATUS_OK, i->servers, i->context);
+ }
+ goto out;
+ }
+
+ return TRUE;
+
+ out:
+ silc_client_list_free_servers(client, conn, i->servers);
+ silc_free(i);
+ return FALSE;
+}
+
+/* Resolve server by server ID */
+
+SilcUInt16
+silc_client_get_server_by_id_resolve(SilcClient client,
+ SilcClientConnection conn,
+ SilcServerID *server_id,
+ SilcGetServerCallback completion,
+ void *context)
+{
+ SilcClientGetServerInternal i;
+ SilcServerEntry server;
+ SilcBuffer idp;
+ SilcUInt16 cmd_ident;
+
+ if (!client || !conn || !server_id || !completion)
+ return 0;
+
+ SILC_LOG_DEBUG(("Resolve server by id %s",
+ silc_id_render(server_id, SILC_ID_SERVER)));
+
+ i = silc_calloc(1, sizeof(*i));
+ if (!i)
+ return 0;
+ i->completion = completion;
+ i->context = context;
+ i->servers = silc_dlist_init();
+ if (!i->servers) {
+ silc_free(i);
+ return 0;
+ }
+
+ /* Attach to resolving, if on going */
+ server = silc_client_get_server_by_id(client, conn, server_id);
+ if (server && server->internal.resolve_cmd_ident) {
+ SILC_LOG_DEBUG(("Attach to existing resolving"));
+ silc_client_unref_server(client, conn, server);
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ server->internal.resolve_cmd_ident,
+ silc_client_get_server_cb, i);
+ return server->internal.resolve_cmd_ident;
+ }
+
+ /* Send the command */
+ idp = silc_id_payload_encode(server_id, SILC_ID_SERVER);
+ cmd_ident = silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
+ silc_client_get_server_cb, i, 1,
+ 5, silc_buffer_datalen(idp));
+ silc_buffer_free(idp);
+ if (!cmd_ident && completion)
+ completion(client, conn, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL, context);
+
+ if (server && cmd_ident)
+ server->internal.resolve_cmd_ident = cmd_ident;
+
+ silc_client_unref_server(client, conn, server);
+
+ return cmd_ident;
+}
+
+/************************** Server Entry Routines ***************************/
+