updates.
[silc.git] / lib / silcclient / client.c
index 583d0221f9216325078e1840c3d18259b0989576..dde26d5322c4f05e6a6ee2079d142d3309efa1b0 100644 (file)
@@ -87,8 +87,11 @@ int silc_client_init(SilcClient client)
   silc_client_protocols_register();
 
   /* Initialize the scheduler */
-  silc_schedule_init(&client->io_queue, &client->timeout_queue, 
-                    &client->generic_queue, 5000);
+  client->schedule = silc_schedule_init(&client->io_queue, 
+                                       &client->timeout_queue, 
+                                       &client->generic_queue, 5000);
+  if (!client->schedule)
+    return FALSE;
 
   return TRUE;
 }
@@ -103,8 +106,8 @@ void silc_client_stop(SilcClient client)
   /* Stop the scheduler, although it might be already stopped. This
      doesn't hurt anyone. This removes all the tasks and task queues,
      as well. */
-  silc_schedule_stop();
-  silc_schedule_uninit();
+  silc_schedule_stop(client->schedule);
+  silc_schedule_uninit(client->schedule);
 
   silc_client_protocols_unregister();
 
@@ -120,7 +123,7 @@ void silc_client_run(SilcClient client)
 
   /* Start the scheduler, the heart of the SILC client. When this returns
      the program will be terminated. */
-  silc_schedule();
+  silc_schedule(client->schedule);
 }
 
 /* Allocates and adds new connection to the client. This adds the allocated
@@ -247,7 +250,7 @@ silc_client_connect_to_server_internal(SilcClientInternalConnectContext *ctx)
                                 SILC_TASK_FD,
                                 SILC_TASK_PRI_NORMAL);
   silc_task_reset_iotype(ctx->task, SILC_TASK_WRITE);
-  silc_schedule_set_listen_fd(sock, ctx->task->iomask);
+  silc_schedule_set_listen_fd(ctx->client->schedule, sock, ctx->task->iomask);
 
   ctx->sock = sock;
 
@@ -377,7 +380,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
                       ctx->port, ctx->host);
 
       /* Unregister old connection try */
-      silc_schedule_unset_listen_fd(fd);
+      silc_schedule_unset_listen_fd(client->schedule, fd);
       silc_net_close_connection(fd);
       silc_task_unregister(client->io_queue, ctx->task);
 
@@ -388,7 +391,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
       /* Connection failed and we won't try anymore */
       client->ops->say(client, conn, "Could not connect to server %s: %s",
                       ctx->host, strerror(opt));
-      silc_schedule_unset_listen_fd(fd);
+      silc_schedule_unset_listen_fd(client->schedule, fd);
       silc_net_close_connection(fd);
       silc_task_unregister(client->io_queue, ctx->task);
       silc_free(ctx);
@@ -400,7 +403,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
     return;
   }
 
-  silc_schedule_unset_listen_fd(fd);
+  silc_schedule_unset_listen_fd(client->schedule, fd);
   silc_task_unregister(client->io_queue, ctx->task);
   silc_free(ctx);
 
@@ -591,7 +594,7 @@ int silc_client_packet_send_real(SilcClient client,
      This call sets the connection both for input and output (the input
      is set always and this call keeps the input setting, actually). 
      Actual data sending is performed by silc_client_packet_process. */
-  SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(sock->sock);
+  SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
 
   /* Mark to socket that data is pending in outgoing buffer. This flag
      is needed if new data is added to the buffer before the earlier
@@ -638,7 +641,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
        back to only for input. When there is again some outgoing data 
        available for this connection it will be set for output as well. 
        This call clears the output setting and sets it only for input. */
-    SILC_CLIENT_SET_CONNECTION_FOR_INPUT(fd);
+    SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, fd);
     SILC_UNSET_OUTBUF_PENDING(sock);
 
     silc_buffer_clear(sock->outbuf);
@@ -1147,7 +1150,7 @@ void silc_client_close_connection(SilcClient client,
     sock = conn->sock;
 
   /* We won't listen for this connection anymore */
-  silc_schedule_unset_listen_fd(sock->sock);
+  silc_schedule_unset_listen_fd(client->schedule, sock->sock);
 
   /* Unregister all tasks */
   silc_task_unregister_by_fd(client->io_queue, sock->sock);
@@ -1156,16 +1159,34 @@ void silc_client_close_connection(SilcClient client,
   /* Close the actual connection */
   silc_net_close_connection(sock->sock);
 
+  /* Cancel any active protocol */
+  if (sock->protocol) {
+    if (sock->protocol->protocol->type == 
+       SILC_PROTOCOL_CLIENT_KEY_EXCHANGE ||
+       sock->protocol->protocol->type == 
+       SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
+      sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+      silc_protocol_execute_final(sock->protocol, client->timeout_queue);
+      sock->protocol = NULL;
+      /* The application will recall this function with these protocols
+        (the ops->connect client operation). */
+      return;
+    } else {
+      sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
+      silc_protocol_execute_final(sock->protocol, client->timeout_queue);
+      sock->protocol = NULL;
+    }
+  }
+
   /* Free everything */
   if (del && sock->user_data) {
     /* XXX Free all client entries and channel entries. */
 
-    client->ops->say(client, sock->user_data,
-                    "Closed connection to host %s", sock->hostname);
-
     /* Clear ID caches */
-    silc_idcache_del_all(conn->client_cache);
-    silc_idcache_del_all(conn->channel_cache);
+    if (conn->client_cache)
+      silc_idcache_del_all(conn->client_cache);
+    if (conn->channel_cache)
+      silc_idcache_del_all(conn->channel_cache);
 
     /* Free data */
     if (conn->remote_host)
@@ -1185,27 +1206,10 @@ void silc_client_close_connection(SilcClient client,
     if (conn->rekey)
       silc_free(conn->rekey);
 
-    conn->sock = NULL;
-    conn->remote_port = 0;
-    conn->remote_type = 0;
-    conn->send_key = NULL;
-    conn->receive_key = NULL;
-    conn->hmac_send = NULL;
-    conn->hmac_receive = NULL;
-    conn->local_id = NULL;
-    conn->local_id_data = NULL;
-    conn->remote_host = NULL;
-    conn->current_channel = NULL;
-    conn->pending_commands = NULL;
-    conn->rekey = NULL;
-
+    memset(conn, 0, sizeof(*conn));
     silc_client_del_connection(client, conn);
   }
 
-  if (sock->protocol) {
-    silc_protocol_free(sock->protocol);
-    sock->protocol = NULL;
-  }
   silc_socket_free(sock);
 }
 
@@ -1408,102 +1412,6 @@ void silc_client_replace_from_channels(SilcClient client,
   silc_idcache_list_free(list);
 }
 
-/* Parses mode mask and returns the mode as string. */
-
-char *silc_client_chmode(uint32 mode, SilcChannelEntry channel)
-{
-  char string[100];
-
-  if (!mode)
-    return NULL;
-
-  memset(string, 0, sizeof(string));
-
-  if (mode & SILC_CHANNEL_MODE_PRIVATE)
-    strncat(string, "p", 1);
-
-  if (mode & SILC_CHANNEL_MODE_SECRET)
-    strncat(string, "s", 1);
-
-  if (mode & SILC_CHANNEL_MODE_PRIVKEY)
-    strncat(string, "k", 1);
-
-  if (mode & SILC_CHANNEL_MODE_INVITE)
-    strncat(string, "i", 1);
-
-  if (mode & SILC_CHANNEL_MODE_TOPIC)
-    strncat(string, "t", 1);
-
-  if (mode & SILC_CHANNEL_MODE_ULIMIT)
-    strncat(string, "l", 1);
-
-  if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
-    strncat(string, "a", 1);
-
-  if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
-    strncat(string, "f", 1);
-
-  if (mode & SILC_CHANNEL_MODE_CIPHER) {
-    char cipher[30];
-    memset(cipher, 0, sizeof(cipher));
-    snprintf(cipher, sizeof(cipher), " c (%s)", 
-            channel->channel_key->cipher->name);
-    strncat(string, cipher, strlen(cipher));
-  }
-
-  if (mode & SILC_CHANNEL_MODE_HMAC) {
-    char hmac[30];
-    memset(hmac, 0, sizeof(hmac));
-    snprintf(hmac, sizeof(hmac), " h (%s)", 
-            channel->hmac->hmac->name);
-    strncat(string, hmac, strlen(hmac));
-  }
-
-  /* Rest of mode is ignored */
-
-  return strdup(string);
-}
-
-/* Parses channel user mode mask and returns te mode as string */
-
-char *silc_client_chumode(uint32 mode)
-{
-  char string[4];
-
-  if (!mode)
-    return NULL;
-
-  memset(string, 0, sizeof(string));
-
-  if (mode & SILC_CHANNEL_UMODE_CHANFO)
-    strncat(string, "f", 1);
-
-  if (mode & SILC_CHANNEL_UMODE_CHANOP)
-    strncat(string, "o", 1);
-
-  return strdup(string);
-}
-
-/* Parses channel user mode and returns it as special mode character. */
-
-char *silc_client_chumode_char(uint32 mode)
-{
-  char string[4];
-
-  if (!mode)
-    return NULL;
-
-  memset(string, 0, sizeof(string));
-
-  if (mode & SILC_CHANNEL_UMODE_CHANFO)
-    strncat(string, "*", 1);
-
-  if (mode & SILC_CHANNEL_UMODE_CHANOP)
-    strncat(string, "@", 1);
-
-  return strdup(string);
-}
-
 /* Registers failure timeout to process the received failure packet
    with timeout. */