Integer type name change.
[silc.git] / lib / silcclient / client_keyagr.c
index 9191edd623036e2ff302be70dbc485f786f33386..87f13e1630cb5bb914622804524e4fc2eb0382a8 100644 (file)
@@ -24,7 +24,8 @@
    and in protocol.c. This file implements the client-to-client key 
    agreement as defined by the SILC protocol. */
 
-#include "clientlibincludes.h"
+#include "silcincludes.h"
+#include "silcclient.h"
 #include "client_internal.h"
 
 SILC_TASK_CALLBACK(silc_client_key_agreement_final);
@@ -36,12 +37,13 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start);
 struct SilcClientKeyAgreementStruct {
   SilcClient client;
   SilcClientConnection conn;
-  int fd;                              /* Listening/connection socket */
-  SilcSocketConnection sock;           /* Remote socket connection */
-  SilcClientEntry client_entry;                /* Destination client */
-  SilcKeyAgreementCallback completion; /* Key agreement completion */
-  void *context;                       /* User context */
-  SilcTask timeout;                    /* Timeout task */
+  int fd;                                /* Listening/connection socket */
+  SilcSocketConnection sock;             /* Remote socket connection */
+  SilcClientEntry client_entry;                  /* Destination client */
+  SilcKeyAgreementCallback completion;   /* Key agreement completion */
+  void *context;                         /* User context */
+  SilcTask timeout;                      /* Timeout task */
+  SilcClientKEInternalContext *proto_ctx; /* Key Exchange protocol context */
 };
 
 /* Packet sending function used by the SKE in the key agreement process. */
@@ -76,8 +78,8 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_close)
 {
   SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
 
-  silc_schedule_unset_listen_fd(ke->sock->sock);
-  silc_schedule_unset_listen_fd(ke->fd);
+  silc_schedule_unset_listen_fd(ke->client->schedule, ke->sock->sock);
+  silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
   silc_net_close_connection(ke->sock->sock);
   silc_net_close_connection(ke->fd);
   silc_socket_free(ke->sock);
@@ -119,16 +121,14 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_final)
     silc_ske_free(ctx->ske);
   if (ctx->dest_id)
     silc_free(ctx->dest_id);
-  silc_task_unregister_by_callback(client->timeout_queue,
-                                  silc_client_failure_callback);
-  silc_task_unregister_by_fd(client->io_queue, ke->fd);
-  silc_schedule_unset_listen_fd(ke->fd);
+  silc_schedule_task_del_by_fd(client->schedule, ke->fd);
+  silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
   silc_net_close_connection(ke->fd);
   if (ke->timeout)
-    silc_task_unregister(client->timeout_queue, ke->timeout);
+    silc_schedule_task_del(client->schedule, ke->timeout);
   silc_client_del_socket(ke->client, ke->sock);
 
-  silc_task_register(client->timeout_queue, 0, 
+  silc_schedule_task_add(client->schedule, 0, 
                     silc_client_key_agreement_close,
                     (void *)ke, 0, 1, 
                     SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
@@ -153,17 +153,17 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
 
   sock = silc_net_accept_connection(ke->fd);
   if (sock < 0) {
-    client->ops->say(client, conn, 
-                    "Could not accept key agreement connection: ", 
-                    strerror(errno));
+    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
+                              "Could not accept key agreement connection: ", 
+                              strerror(errno));
     ke->client_entry->ke = NULL;
     ke->completion(ke->client, ke->conn, ke->client_entry, 
                   SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
-    silc_task_unregister_by_fd(client->io_queue, ke->fd);
-    silc_schedule_unset_listen_fd(ke->fd);
+    silc_schedule_task_del_by_fd(client->schedule, ke->fd);
+    silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
     silc_net_close_connection(ke->fd);
     if (ke->timeout)
-      silc_task_unregister(client->timeout_queue, ke->timeout);
+      silc_schedule_task_del(client->schedule, ke->timeout);
     silc_free(ke);
     return;
   }
@@ -181,16 +181,16 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
   /* Perform name and address lookups for the remote host. */
   silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
   if (!newsocket->hostname && !newsocket->ip) {
-    client->ops->say(client, conn
-                    "Could not resolve the remote IP or hostname");
+    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT
+                              "Could not resolve the remote IP or hostname");
     ke->client_entry->ke = NULL;
     ke->completion(ke->client, ke->conn, ke->client_entry, 
                   SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
-    silc_task_unregister_by_fd(client->io_queue, ke->fd);
-    silc_schedule_unset_listen_fd(ke->fd);
+    silc_schedule_task_del_by_fd(client->schedule, ke->fd);
+    silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
     silc_net_close_connection(ke->fd);
     if (ke->timeout)
-      silc_task_unregister(client->timeout_queue, ke->timeout);
+      silc_schedule_task_del(client->schedule, ke->timeout);
     silc_free(ke);
     return;
   }
@@ -203,12 +203,13 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
      sent as context for the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->client = client;
-  proto_ctx->sock = newsocket;
+  proto_ctx->sock = silc_socket_dup(newsocket);
   proto_ctx->rng = client->rng;
   proto_ctx->responder = TRUE;
   proto_ctx->context = context;
   proto_ctx->send_packet = silc_client_key_agreement_send_packet;
   proto_ctx->verify = silc_client_protocol_ke_verify_key;
+  ke->proto_ctx = proto_ctx;
 
   /* Prepare the connection for key exchange protocol. We allocate the
      protocol but will not start it yet. The connector will be the
@@ -244,12 +245,12 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
     silc_client_del_socket(ke->client, ke->sock);
     silc_socket_free(ke->sock);
   }
+  if (ke->proto_ctx && ke->proto_ctx->ske)
+    silc_ske_free(ke->proto_ctx->ske);
   ke->client_entry->ke = NULL;
-  silc_task_unregister_by_callback(ke->client->timeout_queue,
-                                  silc_client_failure_callback);
   if (ke->fd)
-    silc_task_unregister_by_fd(ke->client->io_queue, ke->fd);
-  silc_schedule_unset_listen_fd(ke->fd);
+    silc_schedule_task_del_by_fd(ke->client->schedule, ke->fd);
+  silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
   silc_net_close_connection(ke->fd);
   silc_free(ke);
 }
@@ -283,6 +284,10 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
    If remote side decides to ignore the request the `completion' will be
    called after the specified timeout, `timeout_secs'. 
 
+   NOTE: If the `hostname' and the `port' was not provided the `completion'
+   will not be called at all since this does nothing more than sending
+   a packet to the remote host.
+
    NOTE: There can be only one active key agreement for one client entry.
    Before setting new one, the old one must be finished (it is finished
    after calling the completion callback) or the function 
@@ -291,9 +296,10 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
 void silc_client_send_key_agreement(SilcClient client,
                                    SilcClientConnection conn,
                                    SilcClientEntry client_entry,
-                                   char *hostname,
+                                   const char *hostname,
+                                   const char *bindhost,
                                    int port,
-                                   uint32 timeout_secs,
+                                   SilcUInt32 timeout_secs,
                                    SilcKeyAgreementCallback completion,
                                    void *context)
 {
@@ -301,23 +307,30 @@ void silc_client_send_key_agreement(SilcClient client,
   SilcClientKeyAgreement ke = NULL;
   SilcBuffer buffer;
 
-  assert(client_entry);
-
-  if (client_entry->ke)
+  if (!client_entry || client_entry->ke)
     return;
 
-  /* Create the listener if hostname and port was provided */
+  /* Create the listener if hostname and port was provided.
+   * also, use bindhost if it was specified.
+   */
+   
   if (hostname) {
     ke = silc_calloc(1, sizeof(*ke));
-    ke->fd = silc_net_create_server(port, hostname);
+    
+    if (bindhost)
+      ke->fd = silc_net_create_server(port, bindhost);
+    else
+      ke->fd = silc_net_create_server(port, hostname);
 
     if (ke->fd < 0) {
-      client->ops->say(client, conn, 
-                      "Cannot create listener on %s on port %d: %s", 
-                      hostname, port, strerror(errno));
+      client->internal->ops->say(
+                    client, conn, SILC_CLIENT_MESSAGE_ERROR, 
+                    "Cannot create listener on %s on port %d: %s", 
+                    (bindhost) ? bindhost:hostname, port, strerror(errno));
       completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
                 NULL, context);
       silc_free(ke);
+
       return;
     }
 
@@ -327,21 +340,21 @@ void silc_client_send_key_agreement(SilcClient client,
     ke->completion = completion;
     ke->context = context;
 
-    /* Add listener task to the queue. This task receives the key 
+    /* Add listener task to the scheduler. This task receives the key 
        negotiations. */
-    silc_task_register(client->io_queue, ke->fd,
-                      silc_client_process_key_agreement,
-                      (void *)ke, 0, 0, 
-                      SILC_TASK_FD,
-                      SILC_TASK_PRI_NORMAL);
+    silc_schedule_task_add(client->schedule, ke->fd,
+                          silc_client_process_key_agreement,
+                          (void *)ke, 0, 0, 
+                          SILC_TASK_FD,
+                          SILC_TASK_PRI_NORMAL);
 
     /* Register a timeout task that will be executed if the connector
        will not start the key exchange protocol within the specified 
        timeout. */
-    ke->timeout = silc_task_register(client->timeout_queue, 0, 
-                                    silc_client_key_agreement_timeout,
-                                    (void *)ke, timeout_secs, 0, 
-                                    SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
+    ke->timeout = silc_schedule_task_add(client->schedule, 0, 
+                                        silc_client_key_agreement_timeout,
+                                        (void *)ke, timeout_secs, 0, 
+                                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
   }
 
   /* Encode the key agreement payload */
@@ -353,7 +366,8 @@ void silc_client_send_key_agreement(SilcClient client,
   silc_client_packet_send(client, sock, SILC_PACKET_KEY_AGREEMENT,
                          client_entry->id, SILC_ID_CLIENT, NULL, NULL,
                          buffer->data, buffer->len, FALSE);
-  silc_free(buffer);
+  silc_buffer_free(buffer);
+
 }
 
 static int 
@@ -362,19 +376,18 @@ silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
   int sock;
 
   /* Create connection to server asynchronously */
-  sock = silc_net_create_connection_async(ctx->port, ctx->host);
+  sock = silc_net_create_connection_async(NULL, ctx->port, ctx->host);
   if (sock < 0)
     return -1;
 
   /* Register task that will receive the async connect and will
      read the result. */
-  ctx->task = silc_task_register(ctx->client->io_queue, sock, 
-                                silc_client_perform_key_agreement_start,
-                                (void *)ctx, 0, 0, 
-                                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);
+  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
+                                    silc_client_perform_key_agreement_start,
+                                    (void *)ctx, 0, 0, 
+                                    SILC_TASK_FD,
+                                    SILC_TASK_PRI_NORMAL);
+  silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE);
 
   ctx->sock = sock;
 
@@ -420,31 +433,33 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_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 client %s: %s",
-                      ctx->host, strerror(opt));
-      client->ops->say(client, conn, 
-                      "Connecting to port %d of client %s resumed", 
-                      ctx->port, ctx->host);
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                                "Could not connect to client %s: %s",
+                                ctx->host, strerror(opt));
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
+                                "Connecting to port %d of client %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);
+      silc_schedule_task_del(client->schedule, ctx->task);
 
       /* Try again */
       silc_client_connect_to_client_internal(ctx);
       ctx->tries++;
     } else {
       /* Connection failed and we won't try anymore */
-      client->ops->say(client, conn, "Could not connect to client %s: %s",
-                      ctx->host, strerror(opt));
-      silc_schedule_unset_listen_fd(fd);
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                                "Could not connect to client %s: %s",
+                                ctx->host, strerror(opt));
+      silc_schedule_unset_listen_fd(client->schedule, fd);
       silc_net_close_connection(fd);
-      silc_task_unregister(client->io_queue, ctx->task);
+      silc_schedule_task_del(client->schedule, ctx->task);
       silc_free(ctx->host);
       silc_free(ctx);
 
@@ -456,8 +471,8 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
     return;
   }
 
-  silc_schedule_unset_listen_fd(fd);
-  silc_task_unregister(client->io_queue, ctx->task);
+  silc_schedule_unset_listen_fd(client->schedule, fd);
+  silc_schedule_task_del(client->schedule, ctx->task);
 
   ke->fd = fd;
 
@@ -502,7 +517,8 @@ void silc_client_perform_key_agreement(SilcClient client,
 
   SILC_LOG_DEBUG(("Start"));
 
-  assert(client_entry && hostname && port);
+  if (!client_entry || !hostname || !port)
+    return;
 
   ke = silc_calloc(1, sizeof(*ke));
   ke->client = client;
@@ -540,7 +556,8 @@ void silc_client_perform_key_agreement_fd(SilcClient client,
 
   SILC_LOG_DEBUG(("Start"));
 
-  assert(client_entry);
+  if (!client_entry)
+    return;
 
   ke = silc_calloc(1, sizeof(*ke));
   ke->client = client;
@@ -560,12 +577,13 @@ void silc_client_perform_key_agreement_fd(SilcClient client,
      sent as context for the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->client = client;
-  proto_ctx->sock = ke->sock;
+  proto_ctx->sock = silc_socket_dup(ke->sock);
   proto_ctx->rng = client->rng;
   proto_ctx->responder = FALSE;
   proto_ctx->context = ke;
   proto_ctx->send_packet = silc_client_key_agreement_send_packet;
   proto_ctx->verify = silc_client_protocol_ke_verify_key;
+  ke->proto_ctx = proto_ctx;
 
   /* Perform key exchange protocol. */
   silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
@@ -583,7 +601,7 @@ void silc_client_perform_key_agreement_fd(SilcClient client,
   SILC_CLIENT_REGISTER_CONNECTION_FOR_IO(sock);
 
   /* Execute the protocol */
-  protocol->execute(client->timeout_queue, 0, protocol, sock, 0, 0);
+  silc_protocol_execute(protocol, client->schedule, 0, 0);
 }
 
 /* This function can be called to unbind the hostname and the port for
@@ -597,19 +615,25 @@ void silc_client_abort_key_agreement(SilcClient client,
                                     SilcClientConnection conn,
                                     SilcClientEntry client_entry)
 {
-  assert(client_entry);
+  if (!client_entry)
+    return;
 
   if (client_entry->ke) {
+    SilcClientKeyAgreement ke;
+
     if (client_entry->ke->sock) {
       silc_client_del_socket(client_entry->ke->client, client_entry->ke->sock);
       silc_socket_free(client_entry->ke->sock);
     }
-    client_entry->ke = NULL;
-    silc_task_unregister_by_fd(client->io_queue, client_entry->ke->fd);
+    silc_schedule_task_del_by_fd(client->schedule, client_entry->ke->fd);
     if (client_entry->ke->timeout)
-      silc_task_unregister(client->timeout_queue, 
-                          client_entry->ke->timeout);
-    silc_free(client_entry->ke);
+      silc_schedule_task_del(client->schedule, 
+                            client_entry->ke->timeout);
+    ke = client_entry->ke;
+    client_entry->ke = NULL;
+    ke->completion(client, conn, client_entry, 
+                  SILC_KEY_AGREEMENT_ABORTED, NULL, ke->context);
+    silc_free(ke);
   }
 }
 
@@ -621,7 +645,7 @@ static void
 silc_client_key_agreement_resolve_cb(SilcClient client,
                                     SilcClientConnection conn,
                                     SilcClientEntry *clients,
-                                    uint32 clients_count,
+                                    SilcUInt32 clients_count,
                                     void *context)
 {
   SilcPacketContext *packet = (SilcPacketContext *)context;
@@ -634,12 +658,14 @@ silc_client_key_agreement_resolve_cb(SilcClient client,
     goto out;
 
   /* Parse the key agreement payload */
-  payload = silc_key_agreement_payload_parse(packet->buffer);
+  payload = silc_key_agreement_payload_parse(packet->buffer->data,
+                                            packet->buffer->len);
   if (!payload)
     goto out;
 
   /* Call the key_agreement client operation */
-  ret = client->ops->key_agreement(client, conn, clients[0], 
+  ret = client->internal->ops->key_agreement(
+                                  client, conn, clients[0], 
                                   silc_key_agreement_get_hostname(payload),
                                   silc_key_agreement_get_port(payload),
                                   &completion, &completion_context);