returns error condition.
Fixed FD task addition when FD task already exists.
if (fd_stream->fd1 > 0) {
silc_file_close(fd_stream->fd1);
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
if (fd_stream->fd1 > 0) {
silc_file_close(fd_stream->fd1);
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
}
if (fd_stream->fd2 > 0 && fd_stream->fd2 != fd_stream->fd1) {
silc_file_close(fd_stream->fd2);
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
}
if (fd_stream->fd2 > 0 && fd_stream->fd2 != fd_stream->fd1) {
silc_file_close(fd_stream->fd2);
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
void silc_fd_stream_destroy(SilcStream stream)
{
void silc_fd_stream_destroy(SilcStream stream)
{
- SilcFDStream fd_stream = stream;
-
silc_fd_stream_close(stream);
silc_fd_stream_close(stream);
- silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
- silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
silc_free(stream);
}
/* Sets stream notification callback for the stream */
silc_free(stream);
}
/* Sets stream notification callback for the stream */
-void silc_fd_stream_notifier(SilcStream stream,
- SilcSchedule schedule,
- SilcStreamNotifier callback,
- void *context)
+SilcBool silc_fd_stream_notifier(SilcStream stream,
+ SilcSchedule schedule,
+ SilcStreamNotifier callback,
+ void *context)
{
SilcFDStream fd_stream = stream;
{
SilcFDStream fd_stream = stream;
} else {
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
} else {
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd1);
silc_schedule_unset_listen_fd(fd_stream->schedule, fd_stream->fd2);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd1);
+ silc_schedule_task_del_by_fd(fd_stream->schedule, fd_stream->fd2);
/* Check if fd is already added */
if (silc_unlikely(silc_hash_table_find(schedule->fd_queue,
SILC_32_TO_PTR(fd),
/* Check if fd is already added */
if (silc_unlikely(silc_hash_table_find(schedule->fd_queue,
SILC_32_TO_PTR(fd),
- NULL, (void **)&task)))
- goto out;
+ NULL, (void **)&task))) {
+ if (task->valid) {
+ task = NULL;
+ goto out;
+ }
+
+ /* Remove invalid task. We must have unique fd key to hash table. */
+ silc_schedule_task_remove(schedule, task);
+ }
/* Check max tasks */
if (silc_unlikely(schedule->max_tasks > 0 &&
silc_hash_table_count(schedule->fd_queue) >=
schedule->max_tasks)) {
SILC_LOG_WARNING(("Scheduler task limit reached: cannot add new task"));
/* Check max tasks */
if (silc_unlikely(schedule->max_tasks > 0 &&
silc_hash_table_count(schedule->fd_queue) >=
schedule->max_tasks)) {
SILC_LOG_WARNING(("Scheduler task limit reached: cannot add new task"));
goto out;
}
ftask = silc_calloc(1, sizeof(*ftask));
goto out;
}
ftask = silc_calloc(1, sizeof(*ftask));
- if (silc_unlikely(!ftask))
+ if (silc_unlikely(!ftask)) {
+ task = NULL;
SILC_LOG_DEBUG(("New fd task %p fd=%d", ftask, fd));
SILC_LOG_DEBUG(("New fd task %p fd=%d", ftask, fd));
ftask->fd = fd;
/* Add task and schedule it */
ftask->fd = fd;
/* Add task and schedule it */
- silc_hash_table_add(schedule->fd_queue, SILC_32_TO_PTR(fd), ftask);
- schedule_ops.schedule_fd(schedule, schedule->internal, ftask,
- ftask->events);
+ if (!silc_hash_table_add(schedule->fd_queue, SILC_32_TO_PTR(fd), ftask)) {
+ silc_free(ftask);
+ task = NULL;
+ goto out;
+ }
+ if (!schedule_ops.schedule_fd(schedule, schedule->internal,
+ ftask, ftask->events)) {
+ silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(fd));
+ task = NULL;
+ goto out;
+ }
/* fd is unique, so there is only one task with this fd in the table */
if (silc_likely(silc_hash_table_find(schedule->fd_queue,
SILC_32_TO_PTR(fd), NULL,
/* fd is unique, so there is only one task with this fd in the table */
if (silc_likely(silc_hash_table_find(schedule->fd_queue,
SILC_32_TO_PTR(fd), NULL,
+ (void **)&task))) {
+ SILC_LOG_DEBUG(("Deleting task %p", task));
SILC_SCHEDULE_UNLOCK(schedule);
SILC_SCHEDULE_UNLOCK(schedule);
directly if wanted. This can be called multiple times for one file
descriptor to set different iomasks. */
directly if wanted. This can be called multiple times for one file
descriptor to set different iomasks. */
-void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
- SilcTaskEvent mask, SilcBool send_events)
+SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+ SilcTaskEvent mask, SilcBool send_events)
{
SilcTaskFd task;
if (silc_unlikely(!schedule->valid))
{
SilcTaskFd task;
if (silc_unlikely(!schedule->valid))
SILC_SCHEDULE_LOCK(schedule);
if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
NULL, (void **)&task)) {
SILC_SCHEDULE_LOCK(schedule);
if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
NULL, (void **)&task)) {
+ if (!schedule_ops.schedule_fd(schedule, schedule->internal, task, mask)) {
+ SILC_SCHEDULE_UNLOCK(schedule);
+ return FALSE;
+ }
- schedule_ops.schedule_fd(schedule, schedule->internal, task, mask);
if (silc_unlikely(send_events) && mask) {
task->revents = mask;
silc_schedule_dispatch_fd(schedule);
if (silc_unlikely(send_events) && mask) {
task->revents = mask;
silc_schedule_dispatch_fd(schedule);
}
SILC_SCHEDULE_UNLOCK(schedule);
}
SILC_SCHEDULE_UNLOCK(schedule);
-/* Returns the file descriptors current requested event mask. */
+/* Returns the file descriptor's current requested event mask. */
SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
SilcUInt32 fd)
SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
SilcUInt32 fd)
* handle. To receive events for the file descriptor set the correct
* request events with silc_schedule_set_listen_fd function.
*
* handle. To receive events for the file descriptor set the correct
* request events with silc_schedule_set_listen_fd function.
*
+ * The task will be initially set for SILC_TASK_READ events. Setting that
+ * event immediately after this call returns is not necessary.
+ *
***/
#define silc_schedule_task_add_fd(schedule, fd, callback, context) \
silc_schedule_task_add(schedule, fd, callback, context, 0, 0, SILC_TASK_FD)
***/
#define silc_schedule_task_add_fd(schedule, fd, callback, context) \
silc_schedule_task_add(schedule, fd, callback, context, 0, 0, SILC_TASK_FD)
- * void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
- * SilcTaskEvent mask,
- * SilcBool send_events);
+ * SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule,
+ * SilcUInt32 fd,
+ * SilcTaskEvent mask,
+ * SilcBool send_events);
* after the event occurs in reality. In normal cases the `send_events'
* is set to FALSE.
*
* after the event occurs in reality. In normal cases the `send_events'
* is set to FALSE.
*
+ * Returns FALSE if the operation could not performed and TRUE if it
+ * was a success.
+ *
-void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
- SilcTaskEvent mask, SilcBool send_events);
+SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+ SilcTaskEvent mask, SilcBool send_events);
/****f* silcutil/SilcScheduleAPI/silc_schedule_get_fd_events
*
/****f* silcutil/SilcScheduleAPI/silc_schedule_get_fd_events
*
SilcUInt32 data_len);
SilcBool silc_socket_stream_close(SilcStream stream);
void silc_socket_stream_destroy(SilcStream stream);
SilcUInt32 data_len);
SilcBool silc_socket_stream_close(SilcStream stream);
void silc_socket_stream_destroy(SilcStream stream);
-void silc_socket_stream_notifier(SilcStream stream,
- SilcSchedule schedule,
- SilcStreamNotifier callback,
- void *context);
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+ SilcSchedule schedule,
+ SilcStreamNotifier callback,
+ void *context);
SilcSchedule silc_socket_stream_get_schedule(SilcStream stream);
/* Internal async host lookup context. */
SilcSchedule silc_socket_stream_get_schedule(SilcStream stream);
/* Internal async host lookup context. */
- SILC_LOG_DEBUG(("Creating TCP socket stream %p", stream));
+ SILC_LOG_DEBUG(("Creating TCP socket stream %p, sock %lu", stream, sock));
stream->ops = &silc_socket_stream_ops;
stream->sock = sock;
stream->ops = &silc_socket_stream_ops;
stream->sock = sock;
h->ops->destroy(stream);
}
h->ops->destroy(stream);
}
-void silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
- SilcStreamNotifier notifier, void *context)
+SilcBool silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
+ SilcStreamNotifier notifier, void *context)
{
SilcStreamHeader h = stream;
{
SilcStreamHeader h = stream;
- h->ops->notifier(stream, schedule, notifier, context);
+ return h->ops->notifier(stream, schedule, notifier, context);
}
SilcSchedule silc_stream_get_schedule(SilcStream stream)
}
SilcSchedule silc_stream_get_schedule(SilcStream stream)
/* This is called to set a notifier callback to the stream and schedule
the stream. Stream should not be scheduled before calling this
function. If stream does not need scheduler then the scheduler can
/* This is called to set a notifier callback to the stream and schedule
the stream. Stream should not be scheduled before calling this
function. If stream does not need scheduler then the scheduler can
- be ignored. This is called when silc_stream_set_notifier was called. */
- void (*notifier)(SilcStream stream, SilcSchedule schedule,
- SilcStreamNotifier callback, void *context);
+ be ignored. This is called when silc_stream_set_notifier was called.
+ Returns FALSE if the stream could not be scheduled. */
+ SilcBool (*notifier)(SilcStream stream, SilcSchedule schedule,
+ SilcStreamNotifier callback, void *context);
/* This is called to return the associated scheduler, if set. This is
called when silc_stream_get_schedule was called. */
/* This is called to return the associated scheduler, if set. This is
called when silc_stream_get_schedule was called. */
* Closes the stream indicated by `stream'. No data can be read or written
* to the stream after calling this function. Return TRUE if the stream
* could be closed. If action is taken on closed stream the notifier
* Closes the stream indicated by `stream'. No data can be read or written
* to the stream after calling this function. Return TRUE if the stream
* could be closed. If action is taken on closed stream the notifier
- * callback will be called with an error status.
+ * callback may be called with an error status.
*
***/
SilcBool silc_stream_close(SilcStream stream);
*
***/
SilcBool silc_stream_close(SilcStream stream);
- * void silc_stream_set_notifier(SilcStream stream,
- * SilcSchedule schedule,
- * SilcStreamNotifier notifier,
- * void *context);
+ * SilcBool silc_stream_set_notifier(SilcStream stream,
+ * SilcSchedule schedule,
+ * SilcStreamNotifier notifier,
+ * void *context);
*
* DESCRIPTION
*
* Set a notifier callback for the stream indicated by `stream' to be called
* when some action takes place on the stream. This effectively means
* scheduling the stream for various actions, that then eventually will
*
* DESCRIPTION
*
* Set a notifier callback for the stream indicated by `stream' to be called
* when some action takes place on the stream. This effectively means
* scheduling the stream for various actions, that then eventually will
- * be delivered to caller in the `notifier' callback. It is called for
+ * be delivered to caller in the `notifier' callback. It is called for
* example when data is available for reading or writing, or if an error
* occurs. This can be called at any time for valid stream.
* example when data is available for reading or writing, or if an error
* occurs. This can be called at any time for valid stream.
* If `notifier' is set to NULL no callback will be called for the stream,
* and the stream is not scheduled anymore.
*
* 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.
+ *
-void silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
- SilcStreamNotifier notifier, void *context);
+SilcBool silc_stream_set_notifier(SilcStream stream, SilcSchedule schedule,
+ SilcStreamNotifier notifier, void *context);
/****f* silcutil/SilcStreamAPI/silc_stream_get_schedule
*
/****f* silcutil/SilcStreamAPI/silc_stream_get_schedule
*
/* Sets stream notification callback for the stream */
/* Sets stream notification callback for the stream */
-void silc_socket_stream_notifier(SilcStream stream,
- SilcSchedule schedule,
- SilcStreamNotifier callback,
- void *context)
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+ SilcSchedule schedule,
+ SilcStreamNotifier callback,
+ void *context)
{
SilcSocketStream socket_stream = (SilcSocketStream)stream;
SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
{
SilcSocketStream socket_stream = (SilcSocketStream)stream;
SilcSymbianSocket *s = (SilcSymbianSocket *)socket_stream->sock;
socket_stream->notifier = callback;
socket_stream->notifier_context = context;
socket_stream->schedule = schedule;
socket_stream->notifier = callback;
socket_stream->notifier_context = context;
socket_stream->schedule = schedule;
Author: Pekka Riikonen <priikone@silcnet.org>
Author: Pekka Riikonen <priikone@silcnet.org>
- 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
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
if (conn->aborted) {
/** Aborted */
silc_fsm_next(fsm, silc_net_connect_st_finish);
if (conn->aborted) {
/** Aborted */
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
/** Network unreachable */
conn->status = SILC_NET_HOST_UNREACHABLE;
silc_fsm_next(fsm, silc_net_connect_st_finish);
/** Network unreachable */
conn->status = SILC_NET_HOST_UNREACHABLE;
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
/* Set sockaddr for this connection */
if (!silc_net_set_sockaddr(&desthost, conn->ip_addr, conn->port)) {
/** Sockaddr failed */
silc_fsm_next(fsm, silc_net_connect_st_finish);
}
/* Set sockaddr for this connection */
if (!silc_net_set_sockaddr(&desthost, conn->ip_addr, conn->port)) {
/** Sockaddr failed */
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
/* Create the connection socket */
}
/* Create the connection socket */
/** Cannot create socket */
SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
/** Cannot create socket */
SILC_LOG_ERROR(("Cannot create socket: %s", strerror(errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
/* Bind to the local address if provided */
}
/* Bind to the local address if provided */
/** Cannot connect to remote host */
SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
/** Cannot connect to remote host */
SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
silc_schedule_set_listen_fd(silc_fsm_get_schedule(fsm), sock,
SILC_TASK_WRITE, FALSE);
SILC_FSM_EVENT_WAIT(&conn->event);
silc_schedule_set_listen_fd(silc_fsm_get_schedule(fsm), sock,
SILC_TASK_WRITE, FALSE);
SILC_FSM_EVENT_WAIT(&conn->event);
+ return SILC_FSM_CONTINUE;
}
static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
}
static void silc_net_connect_wait_stream(SilcSocketStreamStatus status,
if (conn->aborted) {
/** Aborted */
silc_fsm_next(fsm, silc_net_connect_st_finish);
if (conn->aborted) {
/** Aborted */
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
ret = silc_net_get_socket_opt(conn->sock, SOL_SOCKET, SO_ERROR,
}
ret = silc_net_get_socket_opt(conn->sock, SOL_SOCKET, SO_ERROR,
conn->retry--;
silc_net_close_connection(conn->sock);
silc_fsm_next(fsm, silc_net_connect_st_start);
conn->retry--;
silc_net_close_connection(conn->sock);
silc_fsm_next(fsm, silc_net_connect_st_start);
+ return SILC_FSM_CONTINUE;
}
#if defined(ECONNREFUSED)
}
#if defined(ECONNREFUSED)
/** Connecting failed */
SILC_LOG_DEBUG(("Connecting failed"));
silc_fsm_next(fsm, silc_net_connect_st_finish);
/** Connecting failed */
SILC_LOG_DEBUG(("Connecting failed"));
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
/** Connection created */
}
/** Connection created */
if (conn->aborted) {
/** Aborted */
silc_fsm_next(fsm, silc_net_connect_st_finish);
if (conn->aborted) {
/** Aborted */
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
if (conn->stream_status != SILC_SOCKET_OK) {
}
if (conn->stream_status != SILC_SOCKET_OK) {
else
conn->status = SILC_NET_ERROR;
silc_fsm_next(fsm, silc_net_connect_st_finish);
else
conn->status = SILC_NET_ERROR;
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
/* Set stream information */
}
/* Set stream information */
conn->ip_addr, conn->ip_addr, conn->port);
/** Stream created successfully */
conn->ip_addr, conn->ip_addr, conn->port);
/** Stream created successfully */
- SILC_LOG_DEBUG(("Connected successfully"));
+ SILC_LOG_DEBUG(("Connected successfully, sock %d", conn->sock));
conn->status = SILC_NET_OK;
silc_fsm_next(fsm, silc_net_connect_st_finish);
conn->status = SILC_NET_OK;
silc_fsm_next(fsm, silc_net_connect_st_finish);
+ return SILC_FSM_CONTINUE;
}
SILC_FSM_STATE(silc_net_connect_st_finish)
}
SILC_FSM_STATE(silc_net_connect_st_finish)
silc_async_free(conn->sop);
}
silc_async_free(conn->sop);
}
+ return SILC_FSM_FINISH;
}
static void silc_net_connect_abort(SilcAsyncOperation op, void *context)
}
static void silc_net_connect_abort(SilcAsyncOperation op, void *context)
void silc_net_close_connection(int sock)
{
void silc_net_close_connection(int sock)
{
+ SILC_LOG_DEBUG(("Closing sock %d", sock));
struct epoll_event event;
if (!internal)
struct epoll_event event;
if (!internal)
+ return TRUE;
+
+ SILC_LOG_DEBUG(("Scheduling fd %lu, mask %x", task->fd, event_mask));
- if (task->events & SILC_TASK_READ)
+ if (event_mask & SILC_TASK_READ)
event.events |= (EPOLLIN | EPOLLPRI);
event.events |= (EPOLLIN | EPOLLPRI);
- if (task->events & SILC_TASK_WRITE)
+ if (event_mask & SILC_TASK_WRITE)
event.events |= EPOLLOUT;
/* Zero mask unschedules task */
if (silc_unlikely(!event.events)) {
event.events |= EPOLLOUT;
/* Zero mask unschedules task */
if (silc_unlikely(!event.events)) {
- epoll_ctl(internal->epfd, EPOLL_CTL_DEL, task->fd, &event);
+ if (epoll_ctl(internal->epfd, EPOLL_CTL_DEL, task->fd, &event)) {
+ SILC_LOG_DEBUG(("epoll_ctl (DEL): %s", strerror(errno)));
+ return FALSE;
+ }
return TRUE;
}
/* Schedule the task */
if (silc_unlikely(!task->scheduled)) {
event.data.ptr = task;
return TRUE;
}
/* Schedule the task */
if (silc_unlikely(!task->scheduled)) {
event.data.ptr = task;
- epoll_ctl(internal->epfd, EPOLL_CTL_ADD, task->fd, &event);
+ if (epoll_ctl(internal->epfd, EPOLL_CTL_ADD, task->fd, &event)) {
+ SILC_LOG_DEBUG(("epoll_ctl (ADD): %s", strerror(errno)));
+ return FALSE;
+ }
task->scheduled = TRUE;
return TRUE;
}
/* Schedule for specific mask */
event.data.ptr = task;
task->scheduled = TRUE;
return TRUE;
}
/* Schedule for specific mask */
event.data.ptr = task;
- epoll_ctl(internal->epfd, EPOLL_CTL_MOD, task->fd, &event);
+ if (epoll_ctl(internal->epfd, EPOLL_CTL_MOD, task->fd, &event)) {
+ SILC_LOG_DEBUG(("epoll_ctl (MOD): %s", strerror(errno)));
+ return FALSE;
+ }
#endif /* HAVE_EPOLL_WAIT */
return TRUE;
}
#endif /* HAVE_EPOLL_WAIT */
return TRUE;
}
SilcSocketStream socket_stream = stream;
silc_schedule_unset_listen_fd(socket_stream->schedule, socket_stream->sock);
SilcSocketStream socket_stream = stream;
silc_schedule_unset_listen_fd(socket_stream->schedule, socket_stream->sock);
+ silc_schedule_task_del_by_fd(socket_stream->schedule, socket_stream->sock);
silc_net_close_connection(socket_stream->sock);
return TRUE;
silc_net_close_connection(socket_stream->sock);
return TRUE;
/* Sets stream notification callback for the stream */
/* Sets stream notification callback for the stream */
-void silc_socket_stream_notifier(SilcStream stream,
- SilcSchedule schedule,
- SilcStreamNotifier callback,
- void *context)
+SilcBool silc_socket_stream_notifier(SilcStream stream,
+ SilcSchedule schedule,
+ SilcStreamNotifier callback,
+ void *context)
{
SilcSocketStream socket_stream = stream;
{
SilcSocketStream socket_stream = stream;
if (socket_stream->notifier) {
/* Add the socket to scheduler. Safe to call if already added. */
if (socket_stream->notifier) {
/* Add the socket to scheduler. Safe to call if already added. */
- silc_schedule_task_add_fd(socket_stream->schedule, socket_stream->sock,
- silc_socket_stream_io, socket_stream);
+ if (!silc_schedule_task_add_fd(socket_stream->schedule,
+ socket_stream->sock,
+ silc_socket_stream_io, socket_stream))
+ return FALSE;
/* Initially set socket for reading */
/* Initially set socket for reading */
- silc_schedule_set_listen_fd(socket_stream->schedule, socket_stream->sock,
- SILC_TASK_READ, FALSE);
- silc_schedule_wakeup(socket_stream->schedule);
+ if (!silc_schedule_set_listen_fd(socket_stream->schedule,
+ socket_stream->sock,
+ SILC_TASK_READ, FALSE))
+ return FALSE;
} else {
/* Unschedule the socket */
silc_schedule_unset_listen_fd(socket_stream->schedule,
socket_stream->sock);
silc_schedule_task_del_by_fd(socket_stream->schedule,
socket_stream->sock);
} else {
/* Unschedule the socket */
silc_schedule_unset_listen_fd(socket_stream->schedule,
socket_stream->sock);
silc_schedule_task_del_by_fd(socket_stream->schedule,
socket_stream->sock);
- silc_schedule_wakeup(socket_stream->schedule);
+
+ silc_schedule_wakeup(socket_stream->schedule);
+ return TRUE;