summaryrefslogtreecommitdiffstats
path: root/libssh/src/poll.c
diff options
context:
space:
mode:
Diffstat (limited to 'libssh/src/poll.c')
-rw-r--r--libssh/src/poll.c970
1 files changed, 0 insertions, 970 deletions
diff --git a/libssh/src/poll.c b/libssh/src/poll.c
deleted file mode 100644
index 4e9f19f0..00000000
--- a/libssh/src/poll.c
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * poll.c - poll wrapper
- *
- * This file is part of the SSH Library
- *
- * Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
- * Copyright (c) 2003-2013 by Aris Adamantiadis
- * Copyright (c) 2009 Aleksandar Kanchev
- *
- * The SSH Library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at your
- * option) any later version.
- *
- * The SSH Library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the SSH Library; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- *
- * vim: ts=2 sw=2 et cindent
- */
-
-#include "config.h"
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include "libssh/priv.h"
-#include "libssh/libssh.h"
-#include "libssh/poll.h"
-#include "libssh/socket.h"
-#include "libssh/session.h"
-#ifdef WITH_SERVER
-#include "libssh/server.h"
-#include "libssh/misc.h"
-#endif
-
-
-#ifndef SSH_POLL_CTX_CHUNK
-#define SSH_POLL_CTX_CHUNK 5
-#endif
-
-/**
- * @defgroup libssh_poll The SSH poll functions.
- * @ingroup libssh
- *
- * Add a generic way to handle sockets asynchronously.
- *
- * It's based on poll objects, each of which store a socket, its events and a
- * callback, which gets called whenever an event is set. The poll objects are
- * attached to a poll context, which should be allocated on per thread basis.
- *
- * Polling the poll context will poll all the attached poll objects and call
- * their callbacks (handlers) if any of the socket events are set. This should
- * be done within the main loop of an application.
- *
- * @{
- */
-
-struct ssh_poll_handle_struct {
- ssh_poll_ctx ctx;
- ssh_session session;
- union {
- socket_t fd;
- size_t idx;
- } x;
- short events;
- int lock;
- ssh_poll_callback cb;
- void *cb_data;
-};
-
-struct ssh_poll_ctx_struct {
- ssh_poll_handle *pollptrs;
- ssh_pollfd_t *pollfds;
- size_t polls_allocated;
- size_t polls_used;
- size_t chunk_size;
-};
-
-#ifdef HAVE_POLL
-#include <poll.h>
-
-void ssh_poll_init(void) {
- return;
-}
-
-void ssh_poll_cleanup(void) {
- return;
-}
-
-int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
- return poll((struct pollfd *) fds, nfds, timeout);
-}
-
-#else /* HAVE_POLL */
-
-typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int);
-static poll_fn ssh_poll_emu;
-
-#include <sys/types.h>
-
-#ifdef _WIN32
-#ifndef STRICT
-#define STRICT
-#endif /* STRICT */
-
-#include <time.h>
-#include <windows.h>
-#include <winsock2.h>
-#else /* _WIN32 */
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#endif /* _WIN32 */
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-
-/*
- * This is a poll(2)-emulation using select for systems not providing a native
- * poll implementation.
- *
- * Keep in mind that select is terribly inefficient. The interface is simply not
- * meant to be used with maximum descriptor value greater, say, 32 or so. With
- * a value as high as 1024 on Linux you'll pay dearly in every single call.
- * poll() will be orders of magnitude faster.
- */
-static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
- fd_set readfds, writefds, exceptfds;
- struct timeval tv, *ptv;
- socket_t max_fd;
- int rc;
- nfds_t i;
-
- if (fds == NULL) {
- errno = EFAULT;
- return -1;
- }
-
- FD_ZERO (&readfds);
- FD_ZERO (&writefds);
- FD_ZERO (&exceptfds);
-
- /* compute fd_sets and find largest descriptor */
- for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
- if (fds[i].fd == SSH_INVALID_SOCKET) {
- continue;
- }
-#ifndef _WIN32
- if (fds[i].fd >= FD_SETSIZE) {
- rc = -1;
- break;
- }
-#endif
-
- if (fds[i].events & (POLLIN | POLLRDNORM)) {
- FD_SET (fds[i].fd, &readfds);
- }
- if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
- FD_SET (fds[i].fd, &writefds);
- }
- if (fds[i].events & (POLLPRI | POLLRDBAND)) {
- FD_SET (fds[i].fd, &exceptfds);
- }
- if (fds[i].fd > max_fd &&
- (fds[i].events & (POLLIN | POLLOUT | POLLPRI |
- POLLRDNORM | POLLRDBAND |
- POLLWRNORM | POLLWRBAND))) {
- max_fd = fds[i].fd;
- rc = 0;
- }
- }
-
- if (max_fd == SSH_INVALID_SOCKET || rc == -1) {
- errno = EINVAL;
- return -1;
- }
-
- if (timeout < 0) {
- ptv = NULL;
- } else {
- ptv = &tv;
- if (timeout == 0) {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- } else {
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
- }
- }
-
- rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
- if (rc < 0) {
- return -1;
- }
-
- for (rc = 0, i = 0; i < nfds; i++)
- if (fds[i].fd >= 0) {
- fds[i].revents = 0;
-
- if (FD_ISSET(fds[i].fd, &readfds)) {
- int save_errno = errno;
- char data[64] = {0};
- int ret;
-
- /* support for POLLHUP */
- ret = recv(fds[i].fd, data, 64, MSG_PEEK);
-#ifdef _WIN32
- if ((ret == -1) &&
- (errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
- errno == WSAECONNABORTED || errno == WSAENETRESET)) {
-#else
- if ((ret == -1) &&
- (errno == ESHUTDOWN || errno == ECONNRESET ||
- errno == ECONNABORTED || errno == ENETRESET)) {
-#endif
- fds[i].revents |= POLLHUP;
- } else {
- fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
- }
-
- errno = save_errno;
- }
- if (FD_ISSET(fds[i].fd, &writefds)) {
- fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
- }
-
- if (FD_ISSET(fds[i].fd, &exceptfds)) {
- fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
- }
-
- if (fds[i].revents & ~POLLHUP) {
- rc++;
- }
- } else {
- fds[i].revents = POLLNVAL;
- }
-
- return rc;
-}
-
-void ssh_poll_init(void) {
- ssh_poll_emu = bsd_poll;
-}
-
-void ssh_poll_cleanup(void) {
- ssh_poll_emu = bsd_poll;
-}
-
-int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) {
- return (ssh_poll_emu)(fds, nfds, timeout);
-}
-
-#endif /* HAVE_POLL */
-
-/**
- * @brief Allocate a new poll object, which could be used within a poll context.
- *
- * @param fd Socket that will be polled.
- * @param events Poll events that will be monitored for the socket. i.e.
- * POLLIN, POLLPRI, POLLOUT
- * @param cb Function to be called if any of the events are set.
- * The prototype of cb is:
- * int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd,
- * int revents, void *userdata);
- * @param userdata Userdata to be passed to the callback function. NULL if
- * not needed.
- *
- * @return A new poll object, NULL on error
- */
-
-ssh_poll_handle ssh_poll_new(socket_t fd, short events, ssh_poll_callback cb,
- void *userdata) {
- ssh_poll_handle p;
-
- p = malloc(sizeof(struct ssh_poll_handle_struct));
- if (p == NULL) {
- return NULL;
- }
- ZERO_STRUCTP(p);
-
- p->x.fd = fd;
- p->events = events;
- p->cb = cb;
- p->cb_data = userdata;
-
- return p;
-}
-
-
-/**
- * @brief Free a poll object.
- *
- * @param p Pointer to an already allocated poll object.
- */
-
-void ssh_poll_free(ssh_poll_handle p) {
- if(p->ctx != NULL){
- ssh_poll_ctx_remove(p->ctx,p);
- p->ctx=NULL;
- }
- SAFE_FREE(p);
-}
-
-/**
- * @brief Get the poll context of a poll object.
- *
- * @param p Pointer to an already allocated poll object.
- *
- * @return Poll context or NULL if the poll object isn't attached.
- */
-ssh_poll_ctx ssh_poll_get_ctx(ssh_poll_handle p) {
- return p->ctx;
-}
-
-/**
- * @brief Get the events of a poll object.
- *
- * @param p Pointer to an already allocated poll object.
- *
- * @return Poll events.
- */
-short ssh_poll_get_events(ssh_poll_handle p) {
- return p->events;
-}
-
-/**
- * @brief Set the events of a poll object. The events will also be propagated
- * to an associated poll context.
- *
- * @param p Pointer to an already allocated poll object.
- * @param events Poll events.
- */
-void ssh_poll_set_events(ssh_poll_handle p, short events) {
- p->events = events;
- if (p->ctx != NULL && !p->lock) {
- p->ctx->pollfds[p->x.idx].events = events;
- }
-}
-
-/**
- * @brief Set the file descriptor of a poll object. The FD will also be propagated
- * to an associated poll context.
- *
- * @param p Pointer to an already allocated poll object.
- * @param fd New file descriptor.
- */
-void ssh_poll_set_fd(ssh_poll_handle p, socket_t fd) {
- if (p->ctx != NULL) {
- p->ctx->pollfds[p->x.idx].fd = fd;
- } else {
- p->x.fd = fd;
- }
-}
-
-/**
- * @brief Add extra events to a poll object. Duplicates are ignored.
- * The events will also be propagated to an associated poll context.
- *
- * @param p Pointer to an already allocated poll object.
- * @param events Poll events.
- */
-void ssh_poll_add_events(ssh_poll_handle p, short events) {
- ssh_poll_set_events(p, ssh_poll_get_events(p) | events);
-}
-
-/**
- * @brief Remove events from a poll object. Non-existent are ignored.
- * The events will also be propagated to an associated poll context.
- *
- * @param p Pointer to an already allocated poll object.
- * @param events Poll events.
- */
-void ssh_poll_remove_events(ssh_poll_handle p, short events) {
- ssh_poll_set_events(p, ssh_poll_get_events(p) & ~events);
-}
-
-/**
- * @brief Get the raw socket of a poll object.
- *
- * @param p Pointer to an already allocated poll object.
- *
- * @return Raw socket.
- */
-
-socket_t ssh_poll_get_fd(ssh_poll_handle p) {
- if (p->ctx != NULL) {
- return p->ctx->pollfds[p->x.idx].fd;
- }
-
- return p->x.fd;
-}
-/**
- * @brief Set the callback of a poll object.
- *
- * @param p Pointer to an already allocated poll object.
- * @param cb Function to be called if any of the events are set.
- * @param userdata Userdata to be passed to the callback function. NULL if
- * not needed.
- */
-void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata) {
- if (cb != NULL) {
- p->cb = cb;
- p->cb_data = userdata;
- }
-}
-
-/**
- * @brief Create a new poll context. It could be associated with many poll object
- * which are going to be polled at the same time as the poll context. You
- * would need a single poll context per thread.
- *
- * @param chunk_size The size of the memory chunk that will be allocated, when
- * more memory is needed. This is for efficiency reasons,
- * i.e. don't allocate memory for each new poll object, but
- * for the next 5. Set it to 0 if you want to use the
- * library's default value.
- */
-ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size) {
- ssh_poll_ctx ctx;
-
- ctx = malloc(sizeof(struct ssh_poll_ctx_struct));
- if (ctx == NULL) {
- return NULL;
- }
- ZERO_STRUCTP(ctx);
-
- if (chunk_size == 0) {
- chunk_size = SSH_POLL_CTX_CHUNK;
- }
-
- ctx->chunk_size = chunk_size;
-
- return ctx;
-}
-
-/**
- * @brief Free a poll context.
- *
- * @param ctx Pointer to an already allocated poll context.
- */
-void ssh_poll_ctx_free(ssh_poll_ctx ctx) {
- if (ctx->polls_allocated > 0) {
- while (ctx->polls_used > 0){
- ssh_poll_handle p = ctx->pollptrs[0];
- /*
- * The free function calls ssh_poll_ctx_remove() and decrements
- * ctx->polls_used
- */
- ssh_poll_free(p);
- }
-
- SAFE_FREE(ctx->pollptrs);
- SAFE_FREE(ctx->pollfds);
- }
-
- SAFE_FREE(ctx);
-}
-
-static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) {
- ssh_poll_handle *pollptrs;
- ssh_pollfd_t *pollfds;
-
- pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * new_size);
- if (pollptrs == NULL) {
- return -1;
- }
- ctx->pollptrs = pollptrs;
-
- pollfds = realloc(ctx->pollfds, sizeof(ssh_pollfd_t) * new_size);
- if (pollfds == NULL) {
- pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * ctx->polls_allocated);
- if (pollptrs == NULL) {
- return -1;
- }
- ctx->pollptrs = pollptrs;
- return -1;
- }
-
- ctx->pollfds = pollfds;
- ctx->polls_allocated = new_size;
-
- return 0;
-}
-
-/**
- * @brief Add a poll object to a poll context.
- *
- * @param ctx Pointer to an already allocated poll context.
- * @param p Pointer to an already allocated poll object.
- *
- * @return 0 on success, < 0 on error
- */
-int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) {
- socket_t fd;
-
- if (p->ctx != NULL) {
- /* already attached to a context */
- return -1;
- }
-
- if (ctx->polls_used == ctx->polls_allocated &&
- ssh_poll_ctx_resize(ctx, ctx->polls_allocated + ctx->chunk_size) < 0) {
- return -1;
- }
-
- fd = p->x.fd;
- p->x.idx = ctx->polls_used++;
- ctx->pollptrs[p->x.idx] = p;
- ctx->pollfds[p->x.idx].fd = fd;
- ctx->pollfds[p->x.idx].events = p->events;
- ctx->pollfds[p->x.idx].revents = 0;
- p->ctx = ctx;
-
- return 0;
-}
-
-/**
- * @brief Add a socket object to a poll context.
- *
- * @param ctx Pointer to an already allocated poll context.
- * @param s A SSH socket handle
- *
- * @return 0 on success, < 0 on error
- */
-int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, ssh_socket s) {
- ssh_poll_handle p_in, p_out;
- int ret;
- p_in=ssh_socket_get_poll_handle_in(s);
- if(p_in==NULL)
- return -1;
- ret = ssh_poll_ctx_add(ctx,p_in);
- if(ret != 0)
- return ret;
- p_out=ssh_socket_get_poll_handle_out(s);
- if(p_in != p_out)
- ret = ssh_poll_ctx_add(ctx,p_out);
- return ret;
-}
-
-
-/**
- * @brief Remove a poll object from a poll context.
- *
- * @param ctx Pointer to an already allocated poll context.
- * @param p Pointer to an already allocated poll object.
- */
-void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) {
- size_t i;
-
- i = p->x.idx;
- p->x.fd = ctx->pollfds[i].fd;
- p->ctx = NULL;
-
- ctx->polls_used--;
-
- /* fill the empty poll slot with the last one */
- if (ctx->polls_used > 0 && ctx->polls_used != i) {
- ctx->pollfds[i] = ctx->pollfds[ctx->polls_used];
- ctx->pollptrs[i] = ctx->pollptrs[ctx->polls_used];
- ctx->pollptrs[i]->x.idx = i;
- }
-
- /* this will always leave at least chunk_size polls allocated */
- if (ctx->polls_allocated - ctx->polls_used > ctx->chunk_size) {
- ssh_poll_ctx_resize(ctx, ctx->polls_allocated - ctx->chunk_size);
- }
-}
-
-/**
- * @brief Poll all the sockets associated through a poll object with a
- * poll context. If any of the events are set after the poll, the
- * call back function of the socket will be called.
- * This function should be called once within the programs main loop.
- *
- * @param ctx Pointer to an already allocated poll context.
- * @param timeout An upper limit on the time for which ssh_poll_ctx() will
- * block, in milliseconds. Specifying a negative value
- * means an infinite timeout. This parameter is passed to
- * the poll() function.
- * @returns SSH_OK No error.
- * SSH_ERROR Error happened during the poll.
- * SSH_AGAIN Timeout occured
- */
-
-int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) {
- int rc;
- int i, used;
- ssh_poll_handle p;
- socket_t fd;
- int revents;
-
- if (!ctx->polls_used)
- return SSH_ERROR;
-
- rc = ssh_poll(ctx->pollfds, ctx->polls_used, timeout);
- if(rc < 0)
- return SSH_ERROR;
- if (rc == 0)
- return SSH_AGAIN;
- used = ctx->polls_used;
- for (i = 0; i < used && rc > 0; ) {
- if (!ctx->pollfds[i].revents || ctx->pollptrs[i]->lock) {
- i++;
- } else {
- int ret;
-
- p = ctx->pollptrs[i];
- fd = ctx->pollfds[i].fd;
- revents = ctx->pollfds[i].revents;
- /* avoid having any event caught during callback */
- ctx->pollfds[i].events = 0;
- p->lock = 1;
- if (p->cb && (ret = p->cb(p, fd, revents, p->cb_data)) < 0) {
- if (ret == -2) {
- return -1;
- }
- /* the poll was removed, reload the used counter and start again */
- used = ctx->polls_used;
- i=0;
- } else {
- ctx->pollfds[i].revents = 0;
- ctx->pollfds[i].events = p->events;
- p->lock = 0;
- i++;
- }
-
- rc--;
- }
- }
-
- return rc;
-}
-
-/**
- * @internal
- * @brief gets the default poll structure for the current session,
- * when used in blocking mode.
- * @param session SSH session
- * @returns the default ssh_poll_ctx
- */
-ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session){
- if(session->default_poll_ctx != NULL)
- return session->default_poll_ctx;
- /* 2 is enough for the default one */
- session->default_poll_ctx = ssh_poll_ctx_new(2);
- return session->default_poll_ctx;
-}
-
-/* public event API */
-
-struct ssh_event_fd_wrapper {
- ssh_event_callback cb;
- void * userdata;
-};
-
-struct ssh_event_struct {
- ssh_poll_ctx ctx;
-#ifdef WITH_SERVER
- struct ssh_list *sessions;
-#endif
-};
-
-/**
- * @brief Create a new event context. It could be associated with many
- * ssh_session objects and socket fd which are going to be polled at the
- * same time as the event context. You would need a single event context
- * per thread.
- *
- * @return The ssh_event object on success, NULL on failure.
- */
-ssh_event ssh_event_new(void) {
- ssh_event event;
-
- event = malloc(sizeof(struct ssh_event_struct));
- if (event == NULL) {
- return NULL;
- }
- ZERO_STRUCTP(event);
-
- event->ctx = ssh_poll_ctx_new(2);
- if(event->ctx == NULL) {
- free(event);
- return NULL;
- }
-
-#ifdef WITH_SERVER
- event->sessions = ssh_list_new();
- if(event->sessions == NULL) {
- ssh_poll_ctx_free(event->ctx);
- free(event);
- return NULL;
- }
-#endif
-
- return event;
-}
-
-static int ssh_event_fd_wrapper_callback(ssh_poll_handle p, socket_t fd, int revents,
- void *userdata) {
- struct ssh_event_fd_wrapper *pw = (struct ssh_event_fd_wrapper *)userdata;
-
- (void)p;
- if(pw->cb != NULL) {
- return pw->cb(fd, revents, pw->userdata);
- }
- return 0;
-}
-
-/**
- * @brief Add a fd to the event and assign it a callback,
- * when used in blocking mode.
- * @param event The ssh_event
- * @param fd Socket that will be polled.
- * @param events Poll events that will be monitored for the socket. i.e.
- * POLLIN, POLLPRI, POLLOUT
- * @param cb Function to be called if any of the events are set.
- * The prototype of cb is:
- * int (*ssh_event_callback)(socket_t fd, int revents,
- * void *userdata);
- * @param userdata Userdata to be passed to the callback function. NULL if
- * not needed.
- *
- * @returns SSH_OK on success
- * SSH_ERROR on failure
- */
-int ssh_event_add_fd(ssh_event event, socket_t fd, short events,
- ssh_event_callback cb, void *userdata) {
- ssh_poll_handle p;
- struct ssh_event_fd_wrapper *pw;
-
- if(event == NULL || event->ctx == NULL || cb == NULL
- || fd == SSH_INVALID_SOCKET) {
- return SSH_ERROR;
- }
- pw = malloc(sizeof(struct ssh_event_fd_wrapper));
- if(pw == NULL) {
- return SSH_ERROR;
- }
-
- pw->cb = cb;
- pw->userdata = userdata;
-
- /* pw is freed by ssh_event_remove_fd */
- p = ssh_poll_new(fd, events, ssh_event_fd_wrapper_callback, pw);
- if(p == NULL) {
- free(pw);
- return SSH_ERROR;
- }
-
- if(ssh_poll_ctx_add(event->ctx, p) < 0) {
- free(pw);
- ssh_poll_free(p);
- return SSH_ERROR;
- }
- return SSH_OK;
-}
-
-/**
- * @brief remove the poll handle from session and assign them to a event,
- * when used in blocking mode.
- *
- * @param event The ssh_event object
- * @param session The session to add to the event.
- *
- * @returns SSH_OK on success
- * SSH_ERROR on failure
- */
-int ssh_event_add_session(ssh_event event, ssh_session session) {
- unsigned int i;
- ssh_poll_handle p;
-#ifdef WITH_SERVER
- struct ssh_iterator *iterator;
-#endif
-
- if(event == NULL || event->ctx == NULL || session == NULL) {
- return SSH_ERROR;
- }
- if(session->default_poll_ctx == NULL) {
- return SSH_ERROR;
- }
- for(i = 0; i < session->default_poll_ctx->polls_used; i++) {
- p = session->default_poll_ctx->pollptrs[i];
- ssh_poll_ctx_remove(session->default_poll_ctx, p);
- ssh_poll_ctx_add(event->ctx, p);
- /* associate the pollhandler with a session so we can put it back
- * at ssh_event_free()
- */
- p->session = session;
- }
-#ifdef WITH_SERVER
- iterator = ssh_list_get_iterator(event->sessions);
- while(iterator != NULL) {
- if((ssh_session)iterator->data == session) {
- /* allow only one instance of this session */
- return SSH_OK;
- }
- iterator = iterator->next;
- }
- if(ssh_list_append(event->sessions, session) == SSH_ERROR) {
- return SSH_ERROR;
- }
-#endif
- return SSH_OK;
-}
-
-/**
- * @brief Poll all the sockets and sessions associated through an event object.
- * If any of the events are set after the poll, the
- * call back functions of the sessions or sockets will be called.
- * This function should be called once within the programs main loop.
- *
- * @param event The ssh_event object to poll.
- * @param timeout An upper limit on the time for which the poll will
- * block, in milliseconds. Specifying a negative value
- * means an infinite timeout. This parameter is passed to
- * the poll() function.
- * @returns SSH_OK No error.
- * SSH_ERROR Error happened during the poll.
- */
-int ssh_event_dopoll(ssh_event event, int timeout) {
- int rc;
-
- if(event == NULL || event->ctx == NULL) {
- return SSH_ERROR;
- }
- rc = ssh_poll_ctx_dopoll(event->ctx, timeout);
- return rc;
-}
-
-/**
- * @brief Remove a socket fd from an event context.
- *
- * @param event The ssh_event object.
- * @param fd The fd to remove.
- *
- * @returns SSH_OK on success
- * SSH_ERROR on failure
- */
-int ssh_event_remove_fd(ssh_event event, socket_t fd) {
- register size_t i, used;
- int rc = SSH_ERROR;
-
- if(event == NULL || event->ctx == NULL) {
- return SSH_ERROR;
- }
-
- used = event->ctx->polls_used;
- for (i = 0; i < used; i++) {
- if(fd == event->ctx->pollfds[i].fd) {
- ssh_poll_handle p = event->ctx->pollptrs[i];
- if (p->session != NULL){
- /* we cannot free that handle, it's owned by its session */
- continue;
- }
- if (p->cb == ssh_event_fd_wrapper_callback) {
- struct ssh_event_fd_wrapper *pw = p->cb_data;
- SAFE_FREE(pw);
- }
-
- /*
- * The free function calls ssh_poll_ctx_remove() and decrements
- * event->ctx->polls_used.
- */
- ssh_poll_free(p);
- rc = SSH_OK;
-
- /* restart the loop */
- used = event->ctx->polls_used;
- i = 0;
- }
- }
-
- return rc;
-}
-
-/**
- * @brief Remove a session object from an event context.
- *
- * @param event The ssh_event object.
- * @param session The session to remove.
- *
- * @returns SSH_OK on success
- * SSH_ERROR on failure
- */
-int ssh_event_remove_session(ssh_event event, ssh_session session) {
- ssh_poll_handle p;
- register size_t i, used;
- int rc = SSH_ERROR;
-#ifdef WITH_SERVER
- struct ssh_iterator *iterator;
-#endif
-
- if(event == NULL || event->ctx == NULL || session == NULL) {
- return SSH_ERROR;
- }
-
- used = event->ctx->polls_used;
- for(i = 0; i < used; i++) {
- p = event->ctx->pollptrs[i];
- if(p->session == session){
- ssh_poll_ctx_remove(event->ctx, p);
- p->session = NULL;
- ssh_poll_ctx_add(session->default_poll_ctx, p);
- rc = SSH_OK;
- used = 0;
- }
- }
-#ifdef WITH_SERVER
- iterator = ssh_list_get_iterator(event->sessions);
- while(iterator != NULL) {
- if((ssh_session)iterator->data == session) {
- ssh_list_remove(event->sessions, iterator);
- /* there should be only one instance of this session */
- break;
- }
- iterator = iterator->next;
- }
-#endif
-
- return rc;
-}
-
-/**
- * @brief Free an event context.
- *
- * @param event The ssh_event object to free.
- * Note: you have to manually remove sessions and socket
- * fds before freeing the event object.
- *
- */
-void ssh_event_free(ssh_event event) {
- int used, i;
- ssh_poll_handle p;
- if(event == NULL) {
- return;
- }
- if(event->ctx != NULL) {
- used = event->ctx->polls_used;
- for(i = 0; i < used; i++) {
- p = event->ctx->pollptrs[i];
- if(p->session != NULL){
- ssh_poll_ctx_remove(event->ctx, p);
- ssh_poll_ctx_add(p->session->default_poll_ctx, p);
- p->session = NULL;
- used = 0;
- }
- }
-
- ssh_poll_ctx_free(event->ctx);
- }
-#ifdef WITH_SERVER
- if(event->sessions != NULL) {
- ssh_list_free(event->sessions);
- }
-#endif
- free(event);
-}
-
-/** @} */
-
-/* vim: set ts=4 sw=4 et cindent: */