From e9f2575973091102bedbd22ebf243122b4b25ed8 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 14 Sep 2006 20:05:19 +0000 Subject: [PATCH] Configurable lookup for network listener creation. --- lib/silcutil/silcfdstream.c | 10 +- lib/silcutil/silcnet.h | 11 +- lib/silcutil/silcnet_i.h | 3 +- lib/silcutil/silcschedule.c | 282 ++++++++++++++++---------------- lib/silcutil/unix/silcunixnet.c | 9 +- 5 files changed, 168 insertions(+), 147 deletions(-) diff --git a/lib/silcutil/silcfdstream.c b/lib/silcutil/silcfdstream.c index db9bd9d7..a5ce7b87 100644 --- a/lib/silcutil/silcfdstream.c +++ b/lib/silcutil/silcfdstream.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 Pekka Riikonen + Copyright (C) 2005 - 2006 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 @@ -19,6 +19,8 @@ #include "silc.h" +/************************** Types and definitions ***************************/ + #define SILC_IS_FD_STREAM(s) (s->ops == &silc_fd_stream_ops) const SilcStreamOps silc_fd_stream_ops; @@ -34,6 +36,9 @@ typedef struct { int error; } *SilcFDStream; + +/************************ Static utility functions **************************/ + /* The IO process callback that calls the notifier callback to upper layer. */ SILC_TASK_CALLBACK(silc_fd_stream_io) @@ -57,6 +62,9 @@ SILC_TASK_CALLBACK(silc_fd_stream_io) } } + +/****************************** Public API **********************************/ + /* Create file descriptor stream */ SilcStream silc_fd_stream_create(int fd) diff --git a/lib/silcutil/silcnet.h b/lib/silcutil/silcnet.h index b5bbd2d4..6e7d35ed 100644 --- a/lib/silcutil/silcnet.h +++ b/lib/silcutil/silcnet.h @@ -109,8 +109,8 @@ typedef void (*SilcNetCallback)(SilcNetStatus status, * * SilcNetListener * silc_net_tcp_create_listener(const char **local_ip_addr, - * SilcUInt32 local_ip_count, - * int port, SilcBool require_fqdn, + * SilcUInt32 local_ip_count, int port, + * SilcBool lookup, SilcBool require_fqdn, * SilcSchedule schedule, * SilcNetCallback callback, void *context); * @@ -123,13 +123,14 @@ typedef void (*SilcNetCallback)(SilcNetStatus status, * `local_ip_count' many IP addresses provided in `local_ip_addr' table. * On success returns the SilcNetListener context, or NULL on error. * If `require_fqdn' is TRUE the listener will require that the incoming - * connection has FQDN to be able to connect. + * connection has FQDN to be able to connect. If the `lookup' is TRUE + * then the incoming connection hostname will be resolved. * ***/ SilcNetListener silc_net_tcp_create_listener(const char **local_ip_addr, - SilcUInt32 local_ip_count, - int port, SilcBool require_fqdn, + SilcUInt32 local_ip_count, int port, + SilcBool lookup, SilcBool require_fqdn, SilcSchedule schedule, SilcNetCallback callback, void *context); diff --git a/lib/silcutil/silcnet_i.h b/lib/silcutil/silcnet_i.h index 1da16a97..7cc356e2 100644 --- a/lib/silcutil/silcnet_i.h +++ b/lib/silcutil/silcnet_i.h @@ -30,8 +30,9 @@ struct SilcNetListenerStruct { SilcNetCallback callback; void *context; int *socks; - unsigned int socks_count : 31; + unsigned int socks_count : 30; unsigned int require_fqdn : 1; + unsigned int lookup : 1; }; #endif /* SILCNET_I_H */ diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index d60b6d30..50c6f5dd 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -20,6 +20,8 @@ #include "silc.h" +/************************** Types and definitions ***************************/ + /* Platform specific implementation */ extern const SilcScheduleOps schedule_ops; @@ -28,6 +30,9 @@ static void silc_schedule_dispatch_fd(SilcSchedule schedule); static void silc_schedule_dispatch_timeout(SilcSchedule schedule, SilcBool dispatch_all); + +/************************ Static utility functions **************************/ + /* Fd task hash table destructor */ static void silc_schedule_fd_destructor(void *key, void *context, @@ -36,94 +41,6 @@ static void silc_schedule_fd_destructor(void *key, void *context, silc_free(context); } -/* Initializes the scheduler. This returns the scheduler context that - is given as arugment usually to all silc_schedule_* functions. - The `max_tasks' indicates the number of maximum tasks that the - scheduler can handle. The `app_context' is application specific - context that is delivered to task callbacks. */ - -SilcSchedule silc_schedule_init(int max_tasks, void *app_context) -{ - SilcSchedule schedule; - - SILC_LOG_DEBUG(("Initializing scheduler")); - - schedule = silc_calloc(1, sizeof(*schedule)); - if (!schedule) - return NULL; - - schedule->fd_queue = - silc_hash_table_alloc(0, silc_hash_uint, NULL, NULL, NULL, - silc_schedule_fd_destructor, NULL, TRUE); - if (!schedule->fd_queue) - return NULL; - - silc_list_init(schedule->timeout_queue, struct SilcTaskTimeoutStruct, next); - - schedule->app_context = app_context; - schedule->valid = TRUE; - schedule->max_tasks = max_tasks; - - /* Allocate scheduler lock */ - silc_mutex_alloc(&schedule->lock); - - /* Initialize the platform specific scheduler. */ - schedule->internal = schedule_ops.init(schedule, app_context); - - return schedule; -} - -/* Uninitializes the schedule. This is called when the program is ready - to end. This removes all tasks and task queues. Returns FALSE if the - scheduler could not be uninitialized. This happens when the scheduler - is still valid and silc_schedule_stop has not been called. */ - -SilcBool silc_schedule_uninit(SilcSchedule schedule) -{ - SILC_LOG_DEBUG(("Uninitializing scheduler")); - - if (schedule->valid == TRUE) - return FALSE; - - /* Dispatch all timeouts before going away */ - SILC_SCHEDULE_LOCK(schedule); - silc_schedule_dispatch_timeout(schedule, TRUE); - SILC_SCHEDULE_UNLOCK(schedule); - - /* Deliver signals before going away */ - if (schedule->signal_tasks) { - schedule_ops.signals_call(schedule, schedule->internal); - schedule->signal_tasks = FALSE; - } - - /* Unregister all tasks */ - silc_schedule_task_remove(schedule, SILC_ALL_TASKS); - silc_schedule_task_remove(schedule, SILC_ALL_TASKS); - - /* Unregister all task queues */ - silc_hash_table_free(schedule->fd_queue); - - /* Uninit the platform specific scheduler. */ - schedule_ops.uninit(schedule, schedule->internal); - - silc_mutex_free(schedule->lock); - silc_free(schedule); - - return TRUE; -} - -/* Stops the schedule even if it is not supposed to be stopped yet. - After calling this, one should call silc_schedule_uninit (after the - silc_schedule has returned). */ - -void silc_schedule_stop(SilcSchedule schedule) -{ - SILC_LOG_DEBUG(("Stopping scheduler")); - SILC_SCHEDULE_LOCK(schedule); - schedule->valid = FALSE; - SILC_SCHEDULE_UNLOCK(schedule); -} - /* Executes file descriptor tasks. Invalid tasks are removed here. */ static void silc_schedule_dispatch_fd(SilcSchedule schedule) @@ -277,6 +194,146 @@ static void silc_schedule_select_timeout(SilcSchedule schedule) } } +/* Removes task from the scheduler. This must be called with scheduler + locked. */ + +static void silc_schedule_task_remove(SilcSchedule schedule, SilcTask task) +{ + SilcTaskFd ftask; + SilcTaskTimeout ttask; + + if (task == SILC_ALL_TASKS) { + SilcTask task; + SilcHashTableList htl; + SilcUInt32 fd; + + /* Delete from fd queue */ + silc_hash_table_list(schedule->fd_queue, &htl); + while (silc_hash_table_get(&htl, (void **)&fd, (void **)&task)) + silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(fd)); + silc_hash_table_list_reset(&htl); + + /* Delete from timeout queue */ + silc_list_start(schedule->timeout_queue); + while ((task = (SilcTask)silc_list_get(schedule->timeout_queue)) + != SILC_LIST_END) { + silc_list_del(schedule->timeout_queue, task); + silc_free(task); + } + + return; + } + + /* Delete from timeout queue */ + if (task->type == 1) { + silc_list_start(schedule->timeout_queue); + while ((ttask = silc_list_get(schedule->timeout_queue)) != SILC_LIST_END) { + if (ttask == (SilcTaskTimeout)task) { + silc_list_del(schedule->timeout_queue, ttask); + silc_free(ttask); + break; + } + } + + return; + } + + /* Delete from fd queue */ + ftask = (SilcTaskFd)task; + silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(ftask->fd)); +} + + +/****************************** Public API **********************************/ + +/* Initializes the scheduler. This returns the scheduler context that + is given as arugment usually to all silc_schedule_* functions. + The `max_tasks' indicates the number of maximum tasks that the + scheduler can handle. The `app_context' is application specific + context that is delivered to task callbacks. */ + +SilcSchedule silc_schedule_init(int max_tasks, void *app_context) +{ + SilcSchedule schedule; + + SILC_LOG_DEBUG(("Initializing scheduler")); + + schedule = silc_calloc(1, sizeof(*schedule)); + if (!schedule) + return NULL; + + schedule->fd_queue = + silc_hash_table_alloc(0, silc_hash_uint, NULL, NULL, NULL, + silc_schedule_fd_destructor, NULL, TRUE); + if (!schedule->fd_queue) + return NULL; + + silc_list_init(schedule->timeout_queue, struct SilcTaskTimeoutStruct, next); + + schedule->app_context = app_context; + schedule->valid = TRUE; + schedule->max_tasks = max_tasks; + + /* Allocate scheduler lock */ + silc_mutex_alloc(&schedule->lock); + + /* Initialize the platform specific scheduler. */ + schedule->internal = schedule_ops.init(schedule, app_context); + + return schedule; +} + +/* Uninitializes the schedule. This is called when the program is ready + to end. This removes all tasks and task queues. Returns FALSE if the + scheduler could not be uninitialized. This happens when the scheduler + is still valid and silc_schedule_stop has not been called. */ + +SilcBool silc_schedule_uninit(SilcSchedule schedule) +{ + SILC_LOG_DEBUG(("Uninitializing scheduler")); + + if (schedule->valid == TRUE) + return FALSE; + + /* Dispatch all timeouts before going away */ + SILC_SCHEDULE_LOCK(schedule); + silc_schedule_dispatch_timeout(schedule, TRUE); + SILC_SCHEDULE_UNLOCK(schedule); + + /* Deliver signals before going away */ + if (schedule->signal_tasks) { + schedule_ops.signals_call(schedule, schedule->internal); + schedule->signal_tasks = FALSE; + } + + /* Unregister all tasks */ + silc_schedule_task_remove(schedule, SILC_ALL_TASKS); + silc_schedule_task_remove(schedule, SILC_ALL_TASKS); + + /* Unregister all task queues */ + silc_hash_table_free(schedule->fd_queue); + + /* Uninit the platform specific scheduler. */ + schedule_ops.uninit(schedule, schedule->internal); + + silc_mutex_free(schedule->lock); + silc_free(schedule); + + return TRUE; +} + +/* Stops the schedule even if it is not supposed to be stopped yet. + After calling this, one should call silc_schedule_uninit (after the + silc_schedule has returned). */ + +void silc_schedule_stop(SilcSchedule schedule) +{ + SILC_LOG_DEBUG(("Stopping scheduler")); + SILC_SCHEDULE_LOCK(schedule); + schedule->valid = FALSE; + SILC_SCHEDULE_UNLOCK(schedule); +} + /* Runs the scheduler once and then returns. */ SilcBool silc_schedule_one(SilcSchedule schedule, int timeout_usecs) @@ -636,55 +693,6 @@ void silc_schedule_task_del_by_all(SilcSchedule schedule, int fd, SILC_SCHEDULE_UNLOCK(schedule); } -/* Removes task from the scheduler. This must be called with scheduler - locked. */ - -static void silc_schedule_task_remove(SilcSchedule schedule, SilcTask task) -{ - SilcTaskFd ftask; - SilcTaskTimeout ttask; - - if (task == SILC_ALL_TASKS) { - SilcTask task; - SilcHashTableList htl; - SilcUInt32 fd; - - /* Delete from fd queue */ - silc_hash_table_list(schedule->fd_queue, &htl); - while (silc_hash_table_get(&htl, (void **)&fd, (void **)&task)) - silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(fd)); - silc_hash_table_list_reset(&htl); - - /* Delete from timeout queue */ - silc_list_start(schedule->timeout_queue); - while ((task = (SilcTask)silc_list_get(schedule->timeout_queue)) - != SILC_LIST_END) { - silc_list_del(schedule->timeout_queue, task); - silc_free(task); - } - - return; - } - - /* Delete from timeout queue */ - if (task->type == 1) { - silc_list_start(schedule->timeout_queue); - while ((ttask = silc_list_get(schedule->timeout_queue)) != SILC_LIST_END) { - if (ttask == (SilcTaskTimeout)task) { - silc_list_del(schedule->timeout_queue, ttask); - silc_free(ttask); - break; - } - } - - return; - } - - /* Delete from fd queue */ - ftask = (SilcTaskFd)task; - silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(ftask->fd)); -} - /* Sets a file descriptor to be listened by scheduler. One can call this directly if wanted. This can be called multiple times for one file descriptor to set different iomasks. */ diff --git a/lib/silcutil/unix/silcunixnet.c b/lib/silcutil/unix/silcunixnet.c index 7bb5b6c5..929ecf38 100644 --- a/lib/silcutil/unix/silcunixnet.c +++ b/lib/silcutil/unix/silcunixnet.c @@ -112,7 +112,8 @@ SILC_TASK_CALLBACK(silc_net_accept) silc_net_set_socket_opt(sock, SOL_SOCKET, SO_REUSEADDR, 1); /* Create socket stream */ - silc_socket_tcp_stream_create(sock, TRUE, listener->require_fqdn, schedule, + silc_socket_tcp_stream_create(sock, listener->lookup, + listener->require_fqdn, schedule, silc_net_accept_stream, listener); } @@ -120,8 +121,8 @@ SILC_TASK_CALLBACK(silc_net_accept) SilcNetListener silc_net_tcp_create_listener(const char **local_ip_addr, - SilcUInt32 local_ip_count, - int port, SilcBool require_fqdn, + SilcUInt32 local_ip_count, int port, + SilcBool lookup, SilcBool require_fqdn, SilcSchedule schedule, SilcNetCallback callback, void *context) { @@ -143,6 +144,8 @@ silc_net_tcp_create_listener(const char **local_ip_addr, listener->schedule = schedule; listener->callback = callback; listener->context = context; + listener->require_fqdn = require_fqdn; + listener->lookup = lookup; if (local_ip_count > 0) { listener->socks = silc_calloc(local_ip_count, sizeof(*listener->socks)); -- 2.24.0