From f2dd07bb06c199bc35b8a69c0828f88c8e028db6 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 26 Dec 2007 11:55:43 +0000 Subject: [PATCH] Added silc_schedule_[set|get]_global. Added many APIs to call silc_schedule_get_global if provided scheduler argument is NULL. --- CHANGES.RUNTIME | 8 ++ TODO | 12 +-- lib/silchttp/silchttpserver.c | 3 + lib/silchttp/silchttpserver.h | 4 +- lib/silcsftp/sftp_client.c | 3 + lib/silcsftp/sftp_server.c | 3 + lib/silcsftp/silcsftp.h | 6 ++ lib/silcutil/silcfsm.c | 7 +- lib/silcutil/silcfsm.h | 11 ++- lib/silcutil/silclog.c | 3 + lib/silcutil/silclog.h | 9 +- lib/silcutil/silcnet.c | 10 +++ lib/silcutil/silcnet.h | 18 ++-- lib/silcutil/silcschedule.c | 114 +++++++++++++++++++++++- lib/silcutil/silcschedule.h | 74 +++++++++++++++ lib/silcutil/silcsocketstream.c | 24 ++++- lib/silcutil/silcsocketstream.h | 6 +- lib/silcutil/silcstream.h | 5 +- lib/silcutil/silcthread_i.h | 1 + lib/silcutil/symbian/silcsymbiannet.cpp | 45 ++++++++-- lib/silcutil/unix/silcunixnet.c | 39 ++++++-- lib/silcutil/win32/silcwin32net.c | 39 ++++++-- 22 files changed, 396 insertions(+), 48 deletions(-) diff --git a/CHANGES.RUNTIME b/CHANGES.RUNTIME index ff6ebd8a..05b131c5 100644 --- a/CHANGES.RUNTIME +++ b/CHANGES.RUNTIME @@ -1,3 +1,11 @@ +Wed Dec 26 13:10:30 EET 2007 Pekka Riikonen + + * Added silc_schedule_[set|get]_global to + lib/silcutil/silcschedule.[ch]. + + * Changed many APIs to call silc_schedule_get_global if provided + scheduler argument is NULL. + Tue Dec 25 18:44:27 EET 2007 Pekka Riikonen * silc_stack_alloc now automatically aligns the requested diff --git a/TODO b/TODO index fd6156b4..31f8c01a 100644 --- a/TODO +++ b/TODO @@ -105,6 +105,8 @@ Runtime library, lib/silcutil/ o silc_getopt routines (***DONE) + o regex from /lib/contrib to lib/silcutil. + o The SILC Event signals. Asynchronous events that can be created, connected to and signalled. Either own event routines or glued into SilcSchedule: @@ -391,16 +393,14 @@ SILC Accelerator Library const char *option; /* Option name */ const char *display_name; /* Option displayable name */ SilcParamType type; /* Option data format */ + void *default_value; /* Option's default value */ + SilcUInt32 default_value_len; /* Default value length */ } *SilcAcceleratorOption; For software accelerator it could be for example: - { "min_threads", "Minimum threads", SILC_PARAM_UINT32 }, - { "max_threads", "Maximum threads", SILC_PARAM_UINT32 }, - - The accelerator itself doesn't have to use the option structure to - parse the options if not wanted. It is defined for the caller so - they can learn the supported options in a well defined way. + { "min_threads", "Minimum threads", SILC_PARAM_UINT32, (void *)2, 4 }, + { "max_threads", "Maximum threads", SILC_PARAM_UINT32, (void *)4, 4 }, o Diffie-Hellman acceleration diff --git a/lib/silchttp/silchttpserver.c b/lib/silchttp/silchttpserver.c index f43b26a3..510d51b0 100644 --- a/lib/silchttp/silchttpserver.c +++ b/lib/silchttp/silchttpserver.c @@ -457,6 +457,9 @@ SilcHttpServer silc_http_server_alloc(const char *ip, SilcUInt16 port, SILC_LOG_DEBUG(("Start HTTP server at %s:%d", ip, port)); + if (!schedule) + schedule = silc_schedule_get_global(); + if (!ip || !schedule || !callback) return FALSE; diff --git a/lib/silchttp/silchttpserver.h b/lib/silchttp/silchttpserver.h index cfc87c15..36faf5a5 100644 --- a/lib/silchttp/silchttpserver.h +++ b/lib/silchttp/silchttpserver.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2006 Pekka Riikonen + Copyright (C) 2006 - 2007 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 @@ -112,6 +112,8 @@ typedef void (*SilcHttpServerCallback)(SilcHttpServer httpd, * `port'. The `callback' with `context' will be called everytime a new * HTTP request comes to the server from a HTTP client. In that callback * the caller must then reply with the requested Web page or with error. + * If the `schedule' is NULL this will call silc_schedule_get_global to + * try to get global scheduler. * ***/ SilcHttpServer silc_http_server_alloc(const char *ip, SilcUInt16 port, diff --git a/lib/silcsftp/sftp_client.c b/lib/silcsftp/sftp_client.c index 59f7dfb6..10eb160c 100644 --- a/lib/silcsftp/sftp_client.c +++ b/lib/silcsftp/sftp_client.c @@ -403,6 +403,9 @@ SilcSFTP silc_sftp_client_start(SilcStream stream, SILC_LOG_DEBUG(("Starting SFTP client")); + if (!schedule) + schedule = silc_schedule_get_global(); + if (!stream) return NULL; diff --git a/lib/silcsftp/sftp_server.c b/lib/silcsftp/sftp_server.c index 549751e8..b22e21fb 100644 --- a/lib/silcsftp/sftp_server.c +++ b/lib/silcsftp/sftp_server.c @@ -361,6 +361,9 @@ SilcSFTP silc_sftp_server_start(SilcStream stream, { SilcSFTPServer server; + if (!schedule) + schedule = silc_schedule_get_global(); + server = silc_calloc(1, sizeof(*server)); if (!server) return NULL; diff --git a/lib/silcsftp/silcsftp.h b/lib/silcsftp/silcsftp.h index 5a2702fc..d2364146 100644 --- a/lib/silcsftp/silcsftp.h +++ b/lib/silcsftp/silcsftp.h @@ -410,6 +410,9 @@ typedef void (*SilcSFTPExtendedCallback)(SilcSFTP sftp, * used to read and write the SFTP packets. The `error_cb' will be called * in case a stream error occurs, such as end of stream. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcSFTP silc_sftp_client_start(SilcStream stream, SilcSchedule schedule, @@ -874,6 +877,9 @@ void silc_sftp_extended(SilcSFTP sftp, * responsible of closing and destroying the `stream'. The `fs' is the * filesystem context allocated by the application. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcSFTP silc_sftp_server_start(SilcStream stream, SilcSchedule schedule, diff --git a/lib/silcutil/silcfsm.c b/lib/silcutil/silcfsm.c index 4ff23bab..5e6fe2a5 100644 --- a/lib/silcutil/silcfsm.c +++ b/lib/silcutil/silcfsm.c @@ -59,8 +59,11 @@ SilcBool silc_fsm_init(SilcFSM fsm, SilcSchedule schedule) { if (!schedule) { - silc_set_errno(SILC_ERR_INVALID_ARGUMENT); - return FALSE; + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } } fsm->fsm_context = fsm_context; diff --git a/lib/silcutil/silcfsm.h b/lib/silcutil/silcfsm.h index c723bad0..366edf70 100644 --- a/lib/silcutil/silcfsm.h +++ b/lib/silcutil/silcfsm.h @@ -403,7 +403,9 @@ do { \ * caller must free the returned context with silc_fsm_free. The * `fsm_context' is delivered to every FSM state function. The `schedule' * is the caller's scheduler and the FSM will be run in the scheduler. - * Returns NULL if system is out of memory. + * If `schedule' is NULL this will call silc_schedule_get_global to try + * get global scheduler. Returns NULL on error or if system is out of + * memory. * * EXAMPLE * @@ -449,7 +451,9 @@ SilcFSM silc_fsm_alloc(void *fsm_context, * as argument. The silc_fsm_free must not be called if this was called. * Returns TRUE if the initialization is Ok or FALSE if error occurred. * This function does not allocate any memory. The `schedule' is the - * caller's scheduler and the FSM will be run in the scheduler. + * caller's scheduler and the FSM will be run in the scheduler. If + * `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. * * EXAMPLE * @@ -482,7 +486,8 @@ SilcBool silc_fsm_init(SilcFSM fsm, * thread context with silc_fsm_free. If the 'real_thread' is TRUE * then the thread will actually be executed in real thread, if platform * supports them. The `thread_context' is delivered to every state - * function in the thread. Returns NULL if the system is out of memory. + * function in the thread. Returns NULL on error or if the system is out + * of memory. * * NOTES * diff --git a/lib/silcutil/silclog.c b/lib/silcutil/silclog.c index 267e7305..d0bec0c1 100644 --- a/lib/silcutil/silclog.c +++ b/lib/silcutil/silclog.c @@ -243,6 +243,9 @@ SilcBool silc_log_set_file(SilcLogType type, char *filename, FILE *fp = NULL; SilcLog log; + if (!scheduler) + scheduler = silc_schedule_get_global(); + log = silc_log_get_context(type); if (!log) return FALSE; diff --git a/lib/silcutil/silclog.h b/lib/silcutil/silclog.h index 80db7783..56c58ec3 100644 --- a/lib/silcutil/silclog.h +++ b/lib/silcutil/silclog.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2006 Pekka Riikonen + Copyright (C) 1997 - 2007 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 @@ -346,8 +346,8 @@ typedef SilcBool (*SilcLogHexdumpCb)(char *file, char *function, int line, * SYNOPSIS * * SilcBool silc_log_set_file(SilcLogType type, char *filename, - * SilcUInt32 maxsize, - * SilcSchedule scheduler); + * SilcUInt32 maxsize, + * SilcSchedule scheduler); * * DESCRIPTION * @@ -359,7 +359,8 @@ typedef SilcBool (*SilcLogHexdumpCb)(char *file, char *function, int line, * You can disable logging for a channel by specifying NULL filename, the * maxsize in this case is not important. The `scheduler' parameter is * needed by the internal logging to allow buffered output and thus to - * save HD activity. + * save HD activity. If `scheduler' is NULL this will call + * silc_schedule_get_global to try to get global scheduler. * ***/ SilcBool silc_log_set_file(SilcLogType type, char *filename, diff --git a/lib/silcutil/silcnet.c b/lib/silcutil/silcnet.c index d2121556..edd982a6 100644 --- a/lib/silcutil/silcnet.c +++ b/lib/silcutil/silcnet.c @@ -300,6 +300,11 @@ void silc_net_gethostbyname_async(const char *name, { SilcNetResolveContext r = silc_calloc(1, sizeof(*r)); + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + } + r->completion = completion; r->context = context; r->prefer_ipv6 = prefer_ipv6; @@ -356,6 +361,11 @@ void silc_net_gethostbyaddr_async(const char *addr, { SilcNetResolveContext r = silc_calloc(1, sizeof(*r)); + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + } + r->completion = completion; r->context = context; r->schedule = schedule; diff --git a/lib/silcutil/silcnet.h b/lib/silcutil/silcnet.h index 4d44eced..b8db06f8 100644 --- a/lib/silcutil/silcnet.h +++ b/lib/silcutil/silcnet.h @@ -98,7 +98,8 @@ typedef void (*SilcNetCallback)(SilcResult status, * is zero (0), operating system will define it automatically. * * The `callback' always delivers valid new stream. It is not called - * with an error status. + * with an error status. If `schedule' is NULL this will call + * silc_schedule_get_global to try to get global scheduler. * ***/ SilcNetListener @@ -136,7 +137,8 @@ silc_net_tcp_create_listener(const char **local_ip_addr, * then the incoming connection hostname will be resolved. * * The `callback' always delivers valid new stream. It is not called - * with an error status. + * with an error status. If `schedule' is NULL this will call + * silc_schedule_get_global to try to get global scheduler. * ***/ SilcNetListener @@ -238,7 +240,8 @@ void silc_net_close_listener(SilcNetListener listener); * The returned SilcAsyncOperation context can be used to control the * asynchronous connecting, such as to abort it. If it is aborted * using silc_async_abort the `callback' will not be called. If NULL - * is returned the operation cannot be aborted. + * is returned the operation cannot be aborted. If `schedule' is NULL + * this will call silc_schedule_get_global to try to get global scheduler. * ***/ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, @@ -277,7 +280,8 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, * To read the packet use silc_stream_read if the remote address was * provided, and silc_net_udp_receive if it was not. * - * Supports IPv6 if the platform supports it. + * Supports IPv6 if the platform supports it. If `schedule' is NULL this + * will call silc_schedule_get_global to try to get global scheduler. * * EXAMPLE * @@ -532,7 +536,8 @@ SilcBool silc_net_gethostbyname(const char *name, SilcBool prefer_ipv6, * Asynchronously resolves the IP address of the hostname indicated * by the `name'. This function returns immediately, and the * `completion' callback will be called after the resolving is - * completed. + * completed. If `schedule' is NULL this will call silc_schedule_get_global + * to try to get global scheduler. * * If the `prefer_ipv6' is TRUE then this will return IPv6 address if it * finds. If FALSE if returns IPv4 address even if it found IPv6 @@ -577,7 +582,8 @@ SilcBool silc_net_gethostbyaddr(const char *addr, char *name, * Asynchronously resolves the hostname for the IP address indicated * by the `addr'. This function returns immediately, and the * `completion' callback will be called after the resolving is - * completed. + * completed. If `schedule' is NULL this will call silc_schedule_get_global + * to try to get global scheduler. * ***/ void silc_net_gethostbyaddr_async(const char *addr, diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index d2ad0c92..476d11f1 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -290,14 +290,14 @@ void silc_schedule_stats(SilcSchedule schedule) { SilcTaskFd ftask; fprintf(stdout, "Schedule %p statistics:\n\n", schedule); - fprintf(stdout, "Num FD tasks : %lu (%lu bytes allocated)\n", + fprintf(stdout, "Num FD tasks : %d (%lu bytes allocated)\n", silc_hash_table_count(schedule->fd_queue), sizeof(*ftask) * silc_hash_table_count(schedule->fd_queue)); - fprintf(stdout, "Num Timeout tasks : %d (%d bytes allocated)\n", + fprintf(stdout, "Num Timeout tasks : %d (%lu bytes allocated)\n", silc_list_count(schedule->timeout_queue), sizeof(struct SilcTaskTimeoutStruct) * silc_list_count(schedule->timeout_queue)); - fprintf(stdout, "Num Timeout freelist : %d (%d bytes allocated)\n", + fprintf(stdout, "Num Timeout freelist : %d (%lu bytes allocated)\n", silc_list_count(schedule->free_tasks), sizeof(struct SilcTaskTimeoutStruct) * silc_list_count(schedule->free_tasks)); @@ -376,6 +376,8 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule) { SilcTask task; + SILC_VERIFY(schedule); + SILC_LOG_DEBUG(("Uninitializing scheduler %p", schedule)); if (schedule->valid == TRUE) @@ -420,6 +422,7 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule) void silc_schedule_stop(SilcSchedule schedule) { SILC_LOG_DEBUG(("Stopping scheduler")); + SILC_VERIFY(schedule); SILC_SCHEDULE_LOCK(schedule); schedule->valid = FALSE; SILC_SCHEDULE_UNLOCK(schedule); @@ -575,6 +578,39 @@ void silc_schedule_set_notify(SilcSchedule schedule, schedule->notify_context = context; } +/* Set global scheduler */ + +void silc_schedule_set_global(SilcSchedule schedule) +{ + SilcTls tls = silc_thread_get_tls(); + + if (!tls) { + /* Try to initialize Tls */ + tls = silc_thread_tls_init(); + SILC_VERIFY(tls); + if (!tls) + return; + } + + SILC_LOG_DEBUG(("Setting global scheduler %p", schedule)); + + tls->schedule = schedule; +} + +/* Return global scheduler */ + +SilcSchedule silc_schedule_get_global(void) +{ + SilcTls tls = silc_thread_get_tls(); + + if (!tls) + return NULL; + + SILC_LOG_DEBUG(("Return global scheduler %p", tls->schedule)); + + return tls->schedule; +} + /* Add new task to the scheduler */ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, @@ -584,6 +620,15 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, { SilcTask task = NULL; + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + if (silc_unlikely(!schedule->valid)) { silc_set_errno(SILC_ERR_NOT_VALID); return NULL; @@ -730,6 +775,15 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, SilcBool silc_schedule_task_del(SilcSchedule schedule, SilcTask task) { + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } + if (silc_unlikely(task == SILC_ALL_TASKS)) { SilcHashTableList htl; @@ -787,6 +841,15 @@ SilcBool silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd) SILC_LOG_DEBUG(("Unregister task by fd %d", fd)); + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } + SILC_SCHEDULE_LOCK(schedule); /* fd is unique, so there is only one task with this fd in the table */ @@ -829,6 +892,15 @@ SilcBool silc_schedule_task_del_by_callback(SilcSchedule schedule, SILC_LOG_DEBUG(("Unregister task by callback")); + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } + SILC_SCHEDULE_LOCK(schedule); /* Delete from fd queue */ @@ -882,6 +954,15 @@ SilcBool silc_schedule_task_del_by_context(SilcSchedule schedule, SILC_LOG_DEBUG(("Unregister task by context")); + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } + SILC_SCHEDULE_LOCK(schedule); /* Delete from fd queue */ @@ -939,6 +1020,15 @@ SilcBool silc_schedule_task_del_by_all(SilcSchedule schedule, int fd, if (fd) return silc_schedule_task_del_by_fd(schedule, fd); + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } + SILC_SCHEDULE_LOCK(schedule); /* Delete from timeout queue */ @@ -973,6 +1063,15 @@ SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd, { SilcTaskFd task; + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } + if (silc_unlikely(!schedule->valid)) { silc_set_errno(SILC_ERR_NOT_VALID); return FALSE; @@ -1012,6 +1111,15 @@ SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule, SilcTaskFd task; SilcTaskEvent event = 0; + if (!schedule) { + schedule = silc_schedule_get_global(); + SILC_VERIFY(schedule); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return 0; + } + } + if (silc_unlikely(!schedule->valid)) { silc_set_errno(SILC_ERR_NOT_VALID); return 0; diff --git a/lib/silcutil/silcschedule.h b/lib/silcutil/silcschedule.h index a7914aec..af2c8cf3 100644 --- a/lib/silcutil/silcschedule.h +++ b/lib/silcutil/silcschedule.h @@ -424,6 +424,47 @@ SilcStack silc_schedule_get_stack(SilcSchedule schedule); void silc_schedule_set_notify(SilcSchedule schedule, SilcTaskNotifyCb notify, void *context); +/****f* silcutil/SilcScheduleAPI/silc_schedule_set_global + * + * SYNOPSIS + * + * void silc_schedule_set_global(SilcSchedule schedule); + * + * DESCRIPTION + * + * Sets global SilcSchedule `schedule' that can be retrieved at any time + * by using silc_schedule_get_global. The global scheduler is global only + * to the current thread. Each thread can have their own global scheduler. + * If each thread must have global scheduler this must be called in each + * thread. If the global scheduler has been set already, new call will + * replace the old one. + * + * This routine is provided only as a convenience function to store + * program's or thread's scheduler in one global place. It is not mandatory + * to call this function in order to use SilcSchedule. + * + * Many routines that require SilcSchedule as an argument will call + * silc_schedule_get_global if the scheduler is not provided to try to + * get global scheduler. Almost all routines in SilcSchedule API will call + * silc_schedule_get_global if the SilcSchedule is not provided as argument. + * + ***/ +void silc_schedule_set_global(SilcSchedule schedule); + +/****f* silcutil/SilcScheduleAPI/silc_schedule_get_global + * + * SYNOPSIS + * + * SilcSchedule silc_schedule_get_global(void); + * + * DESCRIPTION + * + * Returns the thread's global scheduler that was set by calling + * silc_schedule_set_global or NULL if global scheduler has not been set. + * + ***/ +SilcSchedule silc_schedule_get_global(void); + /****f* silcutil/SilcScheduleAPI/silc_schedule_task_add_fd * * SYNOPSIS @@ -445,6 +486,9 @@ void silc_schedule_set_notify(SilcSchedule schedule, * This returns the new task or NULL on error. If a task with `fd' has * already been added this will return the existing task pointer. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ #define silc_schedule_task_add_fd(schedule, fd, callback, context) \ silc_schedule_task_add(schedule, fd, callback, context, 0, 0, SILC_TASK_FD) @@ -466,6 +510,9 @@ void silc_schedule_set_notify(SilcSchedule schedule, * to the `callback' is SILC_TASK_EXPIRE. A task added with zero (0) * timeout will be executed immediately next time tasks are scheduled. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ #define silc_schedule_task_add_timeout(schedule, callback, context, s, u) \ silc_schedule_task_add(schedule, 0, callback, context, s, u, \ @@ -487,6 +534,9 @@ void silc_schedule_set_notify(SilcSchedule schedule, * effect when called. The event delivered to the `callback' is * SILC_TASK_INTERRUPT. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * * NOTES * * One signal may be registered only one callback. Adding second callback @@ -517,6 +567,9 @@ void silc_schedule_set_notify(SilcSchedule schedule, * in task callbacks (including in the task's own task callback) and * in multi-threaded environment in other threads as well. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcBool silc_schedule_task_del(SilcSchedule schedule, SilcTask task); @@ -536,6 +589,9 @@ SilcBool silc_schedule_task_del(SilcSchedule schedule, SilcTask task); * in task callbacks (including in the task's own task callback) and * in multi-threaded environment in other threads as well. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcBool silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd); @@ -556,6 +612,9 @@ SilcBool silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd); * in task callbacks (including in the task's own task callback) and * in multi-threaded environment in other threads as well. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcBool silc_schedule_task_del_by_callback(SilcSchedule schedule, SilcTaskCallback callback); @@ -576,6 +635,9 @@ SilcBool silc_schedule_task_del_by_callback(SilcSchedule schedule, * in task callbacks (including in the task's own task callback) and * in multi-threaded environment in other threads as well. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcBool silc_schedule_task_del_by_context(SilcSchedule schedule, void *context); @@ -597,6 +659,9 @@ SilcBool silc_schedule_task_del_by_context(SilcSchedule schedule, * in task callbacks (including in the task's own task callback) and * in multi-threaded environment in other threads as well. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcBool silc_schedule_task_del_by_all(SilcSchedule schedule, int fd, SilcTaskCallback callback, @@ -627,6 +692,9 @@ SilcBool silc_schedule_task_del_by_all(SilcSchedule schedule, int fd, * after the event occurs in reality. In normal cases the `send_events' * is set to FALSE. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * * Returns FALSE if the operation could not performed and TRUE if it * was a success. * @@ -646,6 +714,9 @@ SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd, * Returns the file descriptor `fd' current requested events mask, * or 0 on error. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule, SilcUInt32 fd); @@ -662,6 +733,9 @@ SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule, * file descriptor `fd'. No events will be detected for the `fd' * after calling this function. * + * If `schedule' is NULL this will call silc_schedule_get_global to try to + * get global scheduler. + * ***/ void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd); diff --git a/lib/silcutil/silcsocketstream.c b/lib/silcutil/silcsocketstream.c index 5e335743..e11fff73 100644 --- a/lib/silcutil/silcsocketstream.c +++ b/lib/silcutil/silcsocketstream.c @@ -152,10 +152,20 @@ silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup, SilcSocketStream stream; SilcSocketHostLookup l; - if (!sock || !schedule) { - SILC_LOG_ERROR(("Missing arguments to silc_socket_tcp_stream_create")); + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + if (callback) + callback(silc_errno, NULL, context); + return NULL; + } + } + + if (!sock) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); if (callback) - callback(SILC_ERR_INVALID_ARGUMENT, NULL, context); + callback(silc_errno, NULL, context); return NULL; } @@ -219,6 +229,14 @@ SilcStream silc_socket_udp_stream_create(SilcSocket sock, SilcBool ipv6, { SilcSocketStream stream; + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + stream = silc_calloc(1, sizeof(*stream)); if (!stream) return NULL; diff --git a/lib/silcutil/silcsocketstream.h b/lib/silcutil/silcsocketstream.h index 42990936..46cce4fa 100644 --- a/lib/silcutil/silcsocketstream.h +++ b/lib/silcutil/silcsocketstream.h @@ -93,7 +93,8 @@ typedef void (*SilcSocketStreamCallback)(SilcResult status, * also return NULL as the `callback' is called immediately. * * If the silc_stream_set_notifier is called the stream is set to - * non-blocking mode. + * non-blocking mode. If `schedule' is NULL this will call + * silc_schedule_get_global to try to get global scheduler. * ***/ SilcAsyncOperation @@ -136,7 +137,8 @@ silc_socket_tcp_stream_create(SilcSocket sock, SilcBool lookup, * This function returns the created SilcStream or NULL on error. * * If the silc_stream_set_notifier is called the stream is set to - * non-blocking mode. + * non-blocking mode. If `schedule' is NULL this will call + * silc_schedule_get_global to try to get global scheduler. * ***/ SilcStream silc_socket_udp_stream_create(SilcSocket sock, diff --git a/lib/silcutil/silcstream.h b/lib/silcutil/silcstream.h index 8195a15f..85364d2a 100644 --- a/lib/silcutil/silcstream.h +++ b/lib/silcutil/silcstream.h @@ -251,9 +251,8 @@ void silc_stream_destroy(SilcStream stream); * If `notifier' is set to NULL no callback will be called for the stream, * and the stream is not scheduled anymore. * - * This function returns FALSE if the `schedule' was provided and the - * stream could not be scheduled. The actual API for `stream' may provide - * access to the actual error information. Returns TRUE on success. + * This function returns FALSE if the stream could not be scheduled. + * Returns TRUE on success. The `schedule' must always be non-NULL. * ***/ SilcBool silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule, diff --git a/lib/silcutil/silcthread_i.h b/lib/silcutil/silcthread_i.h index c67fce08..dfccc4f6 100644 --- a/lib/silcutil/silcthread_i.h +++ b/lib/silcutil/silcthread_i.h @@ -29,6 +29,7 @@ with silc_calloc and freeable with silc_free, and must also be able to pre-allocate from stack. */ typedef struct SilcTlsObject { + SilcSchedule schedule; /* Global scheduler */ void *thread_context; /* Context set with SILC Tls API */ void *platform_context; /* Platform specific context */ char error_reason[256]; /* Reason for the error */ diff --git a/lib/silcutil/symbian/silcsymbiannet.cpp b/lib/silcutil/symbian/silcsymbiannet.cpp index 1895b1dd..c665b3d3 100644 --- a/lib/silcutil/symbian/silcsymbiannet.cpp +++ b/lib/silcutil/symbian/silcsymbiannet.cpp @@ -181,8 +181,18 @@ silc_net_tcp_create_listener(const char **local_ip_addr, SILC_LOG_DEBUG(("Creating TCP listener")); - if (port < 0 || !schedule || !callback) + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (port < 0 || !callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; + } listener = (SilcNetListener)silc_calloc(1, sizeof(*listener)); if (!listener) { @@ -301,8 +311,18 @@ silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports, SILC_LOG_DEBUG(("Creating TCP listener")); - if (!schedule || !callback) + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (!callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; + } listener = (SilcNetListener)silc_calloc(1, sizeof(*listener)); if (!listener) { @@ -600,8 +620,18 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, SilcResult status; TInt ret; - if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + + if (!remote_ip_addr || remote_port < 1 || !callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; + } SILC_LOG_DEBUG(("Creating connection to host %s port %d", remote_ip_addr, remote_port)); @@ -727,8 +757,13 @@ SilcStream silc_net_udp_connect(const char *local_ip_addr, int local_port, SILC_LOG_DEBUG(("Creating UDP stream")); - if (!schedule) - goto err; + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } SILC_LOG_DEBUG(("Binding to local address %s", local_ip_addr ? local_ip_addr : "0.0.0.0")); diff --git a/lib/silcutil/unix/silcunixnet.c b/lib/silcutil/unix/silcunixnet.c index de7eeaee..15720dcd 100644 --- a/lib/silcutil/unix/silcunixnet.c +++ b/lib/silcutil/unix/silcunixnet.c @@ -143,7 +143,15 @@ silc_net_tcp_create_listener(const char **local_ip_addr, SILC_LOG_DEBUG(("Creating TCP listener")); - if (port < 0 || !schedule || !callback) { + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (port < 0 || !callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } @@ -253,7 +261,15 @@ silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports, SILC_LOG_DEBUG(("Creating TCP listener")); - if (!schedule || !callback) { + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (!callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } @@ -397,8 +413,11 @@ silc_net_udp_connect(const char *local_ip_addr, int local_port, SILC_LOG_DEBUG(("Creating UDP stream")); if (!schedule) { - silc_set_errno(SILC_ERR_INVALID_ARGUMENT); - goto err; + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } } /* Bind to local addresses */ @@ -872,8 +891,18 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, { SilcNetConnect conn; - if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + + if (!remote_ip_addr || remote_port < 1 || !callback) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; + } SILC_LOG_DEBUG(("Creating connection to host %s port %d", remote_ip_addr, remote_port)); diff --git a/lib/silcutil/win32/silcwin32net.c b/lib/silcutil/win32/silcwin32net.c index 0aba454f..0501ab82 100644 --- a/lib/silcutil/win32/silcwin32net.c +++ b/lib/silcutil/win32/silcwin32net.c @@ -145,7 +145,15 @@ silc_net_tcp_create_listener(const char **local_ip_addr, SILC_LOG_DEBUG(("Creating TCP listener")); - if (port < 0 || !schedule || !callback) { + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (port < 0 || !callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } @@ -254,7 +262,15 @@ silc_net_tcp_create_listener2(const char *local_ip_addr, int *ports, SILC_LOG_DEBUG(("Creating TCP listener")); - if (!schedule || !callback) { + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } + + if (!callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); goto err; } @@ -398,8 +414,13 @@ silc_net_udp_connect(const char *local_ip_addr, int local_port, SILC_LOG_DEBUG(("Creating UDP stream")); - if (!schedule) - goto err; + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + goto err; + } + } /* Bind to local addresses */ SILC_LOG_DEBUG(("Binding to local address %s", @@ -797,7 +818,15 @@ SilcAsyncOperation silc_net_tcp_connect(const char *local_ip_addr, { SilcNetConnect conn; - if (!remote_ip_addr || remote_port < 1 || !schedule || !callback) { + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; + } + } + + if (!remote_ip_addr || remote_port < 1 || !callback) { silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; } -- 2.24.0