silcsockconn.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2001 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "silcincludes.h"
/* Heartbeat context */
-struct SilcSocketConnectionHB {
- uint32 heartbeat;
+struct SilcSocketConnectionHBStruct {
+ SilcUInt32 heartbeat;
SilcSocketConnectionHBCb hb_callback;
void *hb_context;
- void *timeout_queue;
+ SilcSchedule schedule;
SilcTask hb_task;
SilcSocketConnection sock;
};
+/* Internal async host lookup context. */
+typedef struct {
+ SilcSocketHostLookupCb callback;
+ void *context;
+ SilcSchedule schedule;
+ SilcSocketConnection sock;
+ bool port;
+} *SilcSocketHostLookup;
+
/* Allocates a new socket connection object. The allocated object is
returned to the new_socket argument. */
silc_buffer_free(sock->inbuf);
silc_buffer_free(sock->outbuf);
if (sock->hb) {
- silc_task_unregister(sock->hb->timeout_queue, sock->hb->hb_task);
+ silc_schedule_task_del(sock->hb->schedule, sock->hb->hb_task);
silc_free(sock->hb->hb_context);
silc_free(sock->hb);
}
+ silc_free(sock->ip);
+ silc_free(sock->hostname);
+
memset(sock, 'F', sizeof(*sock));
silc_free(sock);
}
if (hb->hb_callback)
hb->hb_callback(hb->sock, hb->hb_context);
- hb->hb_task = silc_task_register(hb->timeout_queue, hb->sock->sock,
- silc_socket_heartbeat,
- context, hb->heartbeat, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
+ hb->hb_task = silc_schedule_task_add(hb->schedule, hb->sock->sock,
+ silc_socket_heartbeat,
+ context, hb->heartbeat, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_LOW);
}
/* Sets the heartbeat timeout and prepares the socket for performing
`hb_callback' function that is called when the `heartbeat' timeout
expires. The callback `hb_context' won't be touched by the library
but will be freed automatically when calling silc_socket_free. The
- `timeout_queue' is the application's scheduler timeout queue. */
+ `schedule' is the application's scheduler. */
void silc_socket_set_heartbeat(SilcSocketConnection sock,
- uint32 heartbeat,
+ SilcUInt32 heartbeat,
void *hb_context,
SilcSocketConnectionHBCb hb_callback,
- void *timeout_queue)
+ SilcSchedule schedule)
{
-
if (sock->hb) {
- silc_task_unregister(sock->hb->timeout_queue, sock->hb->hb_task);
+ silc_schedule_task_del(schedule, sock->hb->hb_task);
silc_free(sock->hb->hb_context);
silc_free(sock->hb);
}
sock->hb->heartbeat = heartbeat;
sock->hb->hb_context = hb_context;
sock->hb->hb_callback = hb_callback;
- sock->hb->timeout_queue = timeout_queue;
+ sock->hb->schedule = schedule;
sock->hb->sock = sock;
- sock->hb->hb_task = silc_task_register(timeout_queue, sock->sock,
- silc_socket_heartbeat,
- (void *)sock->hb, heartbeat, 0,
- SILC_TASK_TIMEOUT,
- SILC_TASK_PRI_LOW);
+ sock->hb->hb_task = silc_schedule_task_add(schedule, sock->sock,
+ silc_socket_heartbeat,
+ (void *)sock->hb, heartbeat, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_LOW);
+}
+
+/* Finishing timeout callback that will actually call the user specified
+ host lookup callback. This is executed back in the calling thread and
+ not in the lookup thread. */
+
+SILC_TASK_CALLBACK(silc_socket_host_lookup_finish)
+{
+ SilcSocketHostLookup lookup = (SilcSocketHostLookup)context;
+
+ SILC_UNSET_HOST_LOOKUP(lookup->sock);
+
+ /* If the reference counter is 1 we know that we are the only one
+ holding the socket and it thus is considered freed. The lookup
+ is cancelled also and we will not call the final callback. */
+ if (lookup->sock->users == 1) {
+ SILC_LOG_DEBUG(("Async host lookup was cancelled"));
+ silc_free(lookup);
+ silc_socket_free(lookup->sock);
+ return;
+ }
+
+ SILC_LOG_DEBUG(("Async host lookup finished"));
+
+ silc_socket_free(lookup->sock);
+
+ /* Call the final callback. */
+ if (lookup->callback)
+ lookup->callback(lookup->sock, lookup->context);
+
+ silc_free(lookup);
+}
+
+/* The thread function that performs the actual lookup. */
+
+static void *silc_socket_host_lookup_start(void *context)
+{
+ SilcSocketHostLookup lookup = (SilcSocketHostLookup)context;
+ SilcSocketConnection sock = lookup->sock;
+
+ if (lookup->port)
+ sock->port = silc_net_get_remote_port(sock->sock);
+
+ silc_net_check_host_by_sock(sock->sock, &sock->hostname, &sock->ip);
+ if (!sock->hostname && sock->ip)
+ sock->hostname = strdup(sock->ip);
+
+ silc_schedule_task_add(lookup->schedule, sock->sock,
+ silc_socket_host_lookup_finish, lookup, 0, 1,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+ silc_schedule_wakeup(lookup->schedule);
+
+ return NULL;
+}
+
+/* Performs asynchronous host name and IP address lookups for the
+ specified socket connection. This may be called when the socket
+ connection is created and the full IP address and fully qualified
+ domain name information is desired. The `callback' with `context'
+ will be called after the lookup is performed. The `schedule'
+ is the application's scheduler which the lookup routine needs. If
+ the socket connection is freed during the lookup the library will
+ automatically cancel the lookup and the `callback' will not be called. */
+
+void silc_socket_host_lookup(SilcSocketConnection sock,
+ bool port_lookup,
+ SilcSocketHostLookupCb callback,
+ void *context,
+ SilcSchedule schedule)
+{
+ SilcSocketHostLookup lookup;
+
+ SILC_LOG_DEBUG(("Performing async host lookup"));
+
+ lookup = silc_calloc(1, sizeof(*lookup));
+ lookup->sock = silc_socket_dup(sock); /* Increase reference counter */
+ lookup->callback = callback;
+ lookup->context = context;
+ lookup->schedule = schedule;
+ lookup->port = port_lookup;
+
+ SILC_SET_HOST_LOOKUP(sock);
+ silc_thread_create(silc_socket_host_lookup_start, lookup, FALSE);
}