Beispiel #1
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;
}
Beispiel #2
0
/**
 * @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);
}
Beispiel #3
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;
}
Beispiel #4
0
/**
 * @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);
    }
#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;
}
Beispiel #5
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;
    int ret;

    p = ssh_socket_get_poll_handle(s);
    if (p == NULL) {
        return -1;
    }
    ret = ssh_poll_ctx_add(ctx,p);
    return ret;
}
Beispiel #6
0
/**
 * @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() decrements
             * event->ctx->polls_used
             */
            ssh_poll_ctx_remove(event->ctx, p);
            p->session = NULL;
            ssh_poll_ctx_add(session->default_poll_ctx, p);
            rc = SSH_OK;
            /*
             * Restart the loop!
             * A session can initially have two pollhandlers.
             */
            used = event->ctx->polls_used;
            i = 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;
}
Beispiel #7
0
/**
 * @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) {
    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;
    }
    while (session->default_poll_ctx->polls_used > 0) {
        p = session->default_poll_ctx->pollptrs[0];
        /*
         * ssh_poll_ctx_remove() decrements
         * session->default_poll_ctx->polls_used
         */
        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;
}
Beispiel #8
0
/**
 * @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;
    socket_t session_fd;
#ifdef WITH_SERVER
    struct ssh_iterator *iterator;
#endif

    if(event == NULL || event->ctx == NULL || session == NULL) {
        return SSH_ERROR;
    }

    session_fd = ssh_get_fd(session);
    used = event->ctx->polls_used;
    for(i = 0; i < used; i++) {
        if(session_fd == event->ctx->pollfds[i].fd) {
            p = event->ctx->pollptrs[i];
            ssh_poll_ctx_remove(event->ctx, p);
            ssh_poll_ctx_add(session->default_poll_ctx, p);
            rc = SSH_OK;
        }
    }
#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;
}
Beispiel #9
0
/**
 * @brief Add a poll handle to the event.
 *
 * @param   event     the ssh_event
 *
 * @param   p         the poll handle
 *
 * @returns SSH_OK    on success
 *          SSH_ERROR on failure
 */
int ssh_event_add_poll(ssh_event event, ssh_poll_handle p)
{
    return ssh_poll_ctx_add(event->ctx, p);
}