updates.
[silc.git] / lib / silcclient / client.c
index 89aa1c0f4b8e057eeb8d91e56b5b4ac00ded5430..2f857a1fcfc69535881a797c7d7c481c909fe104 100644 (file)
@@ -40,13 +40,15 @@ static void silc_client_packet_parse_type(SilcClient client,
    the client. The `application' is application specific user data pointer
    and caller must free it. */
 
-SilcClient silc_client_alloc(SilcClientOperations *ops, void *application)
+SilcClient silc_client_alloc(SilcClientOperations *ops, void *application,
+                            const char *silc_version)
 {
   SilcClient new_client;
 
   new_client = silc_calloc(1, sizeof(*new_client));
   new_client->application = application;
   new_client->ops = ops;
+  new_client->silc_client_version = strdup(silc_version);
 
   return new_client;
 }
@@ -87,8 +89,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 +108,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 +125,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 +252,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;
 
@@ -274,7 +279,7 @@ int silc_client_connect_to_server(SilcClient client, int port,
 
   conn = silc_client_add_connection(client, host, port, context);
 
-  client->ops->say(client, conn, 
+  client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
                   "Connecting to port %d of server %s", port, host);
 
   /* Allocate internal context for connection process. This is
@@ -332,7 +337,7 @@ int silc_client_start_key_exchange(SilcClient client,
                      &protocol, (void *)proto_ctx,
                      silc_client_connect_to_server_second);
   if (!protocol) {
-    client->ops->say(client, conn, 
+    client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
                     "Error: Could not start authentication protocol");
     return FALSE;
   }
@@ -348,7 +353,7 @@ int silc_client_start_key_exchange(SilcClient client,
   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(fd);
 
   /* Execute the protocol */
-  protocol->execute(client->timeout_queue, 0, protocol, fd, 0, 0);
+  silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
   return TRUE;
 }
 
@@ -366,18 +371,19 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
   SILC_LOG_DEBUG(("Start"));
 
   /* Check the socket status as it might be in error */
-  getsockopt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
+  silc_net_get_socket_opt(fd, SOL_SOCKET, SO_ERROR, &opt, &opt_len);
   if (opt != 0) {
     if (ctx->tries < 2) {
       /* Connection failed but lets try again */
-      client->ops->say(client, conn, "Could not connect to server %s: %s",
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                      "Could not connect to server %s: %s",
                       ctx->host, strerror(opt));
-      client->ops->say(client, conn, 
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
                       "Connecting to port %d of server %s resumed", 
                       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);
 
@@ -386,9 +392,10 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
       ctx->tries++;
     } else {
       /* Connection failed and we won't try anymore */
-      client->ops->say(client, conn, "Could not connect to server %s: %s",
+      client->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                      "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 +407,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);
 
@@ -467,12 +474,8 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
   if (!client->ops->get_auth_method(client, sock->user_data, sock->hostname,
                                    sock->port, &proto_ctx->auth_meth,
                                    &proto_ctx->auth_data, 
-                                   &proto_ctx->auth_data_len)) {
-    client->ops->say(client, ctx->sock->user_data, 
-                    "Could not resolve authentication method to use, "
-                    "assume no authentication");
+                                   &proto_ctx->auth_data_len))
     proto_ctx->auth_meth = SILC_AUTH_NONE;
-  }
 
   /* Free old protocol as it is finished now */
   silc_protocol_free(protocol);
@@ -481,16 +484,13 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_second)
   silc_free(ctx);
   sock->protocol = NULL;
 
-  /* Allocate the authentication protocol. This is allocated here
-     but we won't start it yet. We will be receiving party of this
-     protocol thus we will wait that connecting party will make
-     their first move. */
+  /* Allocate the authenteication protocol and execute it. */
   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_CONNECTION_AUTH, 
                      &sock->protocol, (void *)proto_ctx, 
                      silc_client_connect_to_server_final);
 
   /* Execute the protocol */
-  sock->protocol->execute(client->timeout_queue, 0, sock->protocol, fd, 0, 0);
+  silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
 }
 
 /* Finalizes the connection to the remote SILC server. This is called
@@ -598,7 +598,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
@@ -645,7 +645,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);
@@ -805,10 +805,8 @@ void silc_client_packet_parse_type(SilcClient client,
      * one protocol for connection executing at once hence this
      * success message is for whatever protocol is executing currently.
      */
-    if (sock->protocol) {
-      sock->protocol->execute(client->timeout_queue, 0,
-                             sock->protocol, sock->sock, 0, 0);
-    }
+    if (sock->protocol)
+      silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
     break;
   case SILC_PACKET_FAILURE:
     /*
@@ -883,13 +881,10 @@ void silc_client_packet_parse_type(SilcClient client,
        break;
 
       /* Let the protocol handle the packet */
-      sock->protocol->execute(client->timeout_queue, 0,
-                             sock->protocol, sock->sock, 0, 0);
+      silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
     } else {
       SILC_LOG_ERROR(("Received Key Exchange packet but no key exchange "
                      "protocol active, packet dropped."));
-
-      /* XXX Trigger KE protocol?? Rekey actually! */
     }
     break;
 
@@ -908,8 +903,7 @@ void silc_client_packet_parse_type(SilcClient client,
        proto_ctx->packet = silc_packet_context_dup(packet);
 
        /* Let the protocol handle the packet */
-       sock->protocol->execute(client->timeout_queue, 0, 
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
       } else {
        SilcClientKEInternalContext *proto_ctx = 
          (SilcClientKEInternalContext *)sock->protocol->context;
@@ -925,8 +919,7 @@ void silc_client_packet_parse_type(SilcClient client,
          break;
        
        /* Let the protocol handle the packet */
-       sock->protocol->execute(client->timeout_queue, 0,
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
       }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 1 packet but no key exchange "
@@ -948,8 +941,7 @@ void silc_client_packet_parse_type(SilcClient client,
        proto_ctx->packet = silc_packet_context_dup(packet);
 
        /* Let the protocol handle the packet */
-       sock->protocol->execute(client->timeout_queue, 0, 
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
       } else {
        SilcClientKEInternalContext *proto_ctx = 
          (SilcClientKEInternalContext *)sock->protocol->context;
@@ -965,8 +957,7 @@ void silc_client_packet_parse_type(SilcClient client,
          break;
        
        /* Let the protocol handle the packet */
-       sock->protocol->execute(client->timeout_queue, 0,
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
       }
     } else {
       SILC_LOG_ERROR(("Received Key Exchange 2 packet but no key exchange "
@@ -1031,12 +1022,11 @@ void silc_client_packet_parse_type(SilcClient client,
 
       /* Let the protocol handle the packet */
       if (proto_ctx->responder == FALSE)
-       sock->protocol->execute(client->timeout_queue, 0, 
-                               sock->protocol, sock->sock, 0, 0);
+       silc_protocol_execute(sock->protocol, client->timeout_queue, 0, 0);
       else
        /* Let the protocol handle the packet */
-       sock->protocol->execute(client->timeout_queue, 0
-                               sock->protocol, sock->sock, 0, 100000);
+       silc_protocol_execute(sock->protocol, client->timeout_queue
+                             0, 100000);
     } else {
       SILC_LOG_ERROR(("Received Re-key done packet but no re-key "
                      "protocol active, packet dropped."));
@@ -1068,106 +1058,8 @@ void silc_client_packet_send(SilcClient client,
 {
   SilcPacketContext packetdata;
 
-  SILC_LOG_DEBUG(("Sending packet, type %d", type));
-
-  /* Get data used in the packet sending, keys and stuff */
-  if ((!cipher || !hmac || !dst_id) && sock->user_data) {
-    if (!cipher && ((SilcClientConnection)sock->user_data)->send_key)
-      cipher = ((SilcClientConnection)sock->user_data)->send_key;
-
-    if (!hmac && ((SilcClientConnection)sock->user_data)->hmac_send)
-      hmac = ((SilcClientConnection)sock->user_data)->hmac_send;
-
-    if (!dst_id && ((SilcClientConnection)sock->user_data)->remote_id) {
-      dst_id = ((SilcClientConnection)sock->user_data)->remote_id;
-      dst_id_type = SILC_ID_SERVER;
-    }
-  }
-
-  /* Set the packet context pointers */
-  packetdata.flags = 0;
-  packetdata.type = type;
-  if (sock->user_data && 
-      ((SilcClientConnection)sock->user_data)->local_id_data) {
-    packetdata.src_id = ((SilcClientConnection)sock->user_data)->local_id_data;
-    packetdata.src_id_len = 
-      silc_id_get_len(((SilcClientConnection)sock->user_data)->local_id,
-                     SILC_ID_CLIENT);
-  } else { 
-    packetdata.src_id = silc_calloc(SILC_ID_CLIENT_LEN, sizeof(unsigned char));
-    packetdata.src_id_len = SILC_ID_CLIENT_LEN;
-  }
-  packetdata.src_id_type = SILC_ID_CLIENT;
-  if (dst_id) {
-    packetdata.dst_id = silc_id_id2str(dst_id, dst_id_type);
-    packetdata.dst_id_len = silc_id_get_len(dst_id, dst_id_type);
-    packetdata.dst_id_type = dst_id_type;
-  } else {
-    packetdata.dst_id = NULL;
-    packetdata.dst_id_len = 0;
-    packetdata.dst_id_type = SILC_ID_NONE;
-  }
-  packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
-    packetdata.src_id_len + packetdata.dst_id_len;
-  packetdata.padlen = SILC_PACKET_PADLEN(packetdata.truelen);
-
-  /* Prepare outgoing data buffer for packet sending */
-  silc_packet_send_prepare(sock, 
-                          SILC_PACKET_HEADER_LEN +
-                          packetdata.src_id_len + 
-                          packetdata.dst_id_len,
-                          packetdata.padlen,
-                          data_len);
-
-  SILC_LOG_DEBUG(("Putting data to outgoing buffer, len %d", data_len));
-
-  packetdata.buffer = sock->outbuf;
-
-  /* Put the data to the buffer */
-  if (data && data_len)
-    silc_buffer_put(sock->outbuf, data, data_len);
-
-  /* Create the outgoing packet */
-  silc_packet_assemble(&packetdata);
-
-  /* Encrypt the packet */
-  if (cipher)
-    silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
-
-  SILC_LOG_HEXDUMP(("Packet, len %d", sock->outbuf->len),
-                  sock->outbuf->data, sock->outbuf->len);
-
-  /* Now actually send the packet */
-  silc_client_packet_send_real(client, sock, force_send, FALSE);
-}
-
-void silc_client_packet_send_flush(SilcClient client, 
-                                  SilcSocketConnection sock,
-                                  SilcPacketType type, 
-                                  void *dst_id,
-                                  SilcIdType dst_id_type,
-                                  SilcCipher cipher,
-                                  SilcHmac hmac,
-                                  unsigned char *data, 
-                                  uint32 data_len)
-{
-  SilcPacketContext packetdata;
-
-  /* First flush the packet queue. */
-  
-  if (sock->outbuf->data - sock->outbuf->head)
-    silc_buffer_push(sock->outbuf, 
-                    sock->outbuf->data - sock->outbuf->head);
-  
-  silc_client_packet_send_real(client, sock, TRUE, TRUE);
-  
-  /* The packet has been sent and now it is time to set the connection
-     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(sock->sock);
-  SILC_UNSET_OUTBUF_PENDING(sock);
-  silc_buffer_clear(sock->outbuf);
+  if (!sock)
+    return;
 
   SILC_LOG_DEBUG(("Sending packet, type %d", type));
 
@@ -1239,7 +1131,7 @@ void silc_client_packet_send_flush(SilcClient client,
                   sock->outbuf->data, sock->outbuf->len);
 
   /* Now actually send the packet */
-  silc_client_packet_send_real(client, sock, TRUE, TRUE);
+  silc_client_packet_send_real(client, sock, force_send, FALSE);
 }
 
 /* Closes connection to remote end. Free's all allocated data except
@@ -1262,7 +1154,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);
@@ -1271,16 +1163,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)
@@ -1300,27 +1210,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);
 }
 
@@ -1338,7 +1231,7 @@ void silc_client_disconnected_by_server(SilcClient client,
 
   msg = silc_calloc(message->len + 1, sizeof(char));
   memcpy(msg, message->data, message->len);
-  client->ops->say(client, sock->user_data, msg);
+  client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
   silc_free(msg);
 
   SILC_SET_DISCONNECTED(sock);
@@ -1356,7 +1249,7 @@ void silc_client_error_by_server(SilcClient client,
 
   msg = silc_calloc(message->len + 1, sizeof(char));
   memcpy(msg, message->data, message->len);
-  client->ops->say(client, sock->user_data, msg);
+  client->ops->say(client, sock->user_data, SILC_CLIENT_MESSAGE_AUDIT, msg);
   silc_free(msg);
 }
 
@@ -1369,6 +1262,7 @@ void silc_client_receive_new_id(SilcClient client,
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
   int connecting = FALSE;
+  SilcBuffer sidp;
 
   if (!conn->local_entry)
     connecting = TRUE;
@@ -1406,6 +1300,13 @@ void silc_client_receive_new_id(SilcClient client,
   silc_idcache_add(conn->client_cache, conn->nickname, conn->local_id, 
                   (void *)conn->local_entry, FALSE);
 
+  /* Issue INFO command to fetch the real server name and server information
+     and other stuff. */
+  sidp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
+  silc_client_send_command(client, conn, SILC_COMMAND_INFO,
+                          ++conn->cmd_ident, 1, 2, sidp->data, sidp->len);
+  silc_buffer_free(sidp);
+
   /* Notify application of successful connection. We do it here now that
      we've received the Client ID and are allowed to send traffic. */
   if (connecting)
@@ -1523,102 +1424,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. */
 
@@ -1666,8 +1471,7 @@ SILC_TASK_CALLBACK(silc_client_rekey_callback)
   sock->protocol = protocol;
       
   /* Run the protocol */
-  protocol->execute(client->timeout_queue, 0, protocol, 
-                   sock->sock, 0, 0);
+  silc_protocol_execute(protocol, client->timeout_queue, 0, 0);
 
   /* Re-register re-key timeout */
   silc_task_register(client->timeout_queue, sock->sock, 
@@ -1692,7 +1496,7 @@ SILC_TASK_CALLBACK(silc_client_rekey_final)
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
-    silc_protocol_cancel(client->timeout_queue, protocol);
+    silc_protocol_cancel(protocol, client->timeout_queue);
     silc_protocol_free(protocol);
     sock->protocol = NULL;
     if (ctx->packet)