Ejemplo n.º 1
0
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout)
{
    int rc;
    size_t i, used;
    ssh_poll_handle p;
    socket_t fd;
    int revents;
    struct ssh_timestamp ts;

    if (ctx->polls_used == 0) {
        return SSH_ERROR;
    }

    ssh_timestamp_init(&ts);
    do {
        int tm = ssh_timeout_update(&ts, timeout);
        rc = ssh_poll(ctx->pollfds, ctx->polls_used, tm);
    } while (rc == -1 && errno == EINTR);

    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;
}
Ejemplo n.º 2
0
static void torture_timeout_update(void **state){
    struct ssh_timestamp ts;
    (void) state;
    ssh_timestamp_init(&ts);
    usleep(50000);
    assert_int_equal(ssh_timeout_update(&ts,25), 0);
    assert_in_range(ssh_timeout_update(&ts,30000),29000,29960);
    assert_in_range(ssh_timeout_update(&ts,75),1,40);
    assert_int_equal(ssh_timeout_update(&ts,0),0);
    assert_int_equal(ssh_timeout_update(&ts,-1),-1);
}
Ejemplo n.º 3
0
static void torture_timeout_elapsed(void **state){
    struct ssh_timestamp ts;
    (void) state;
    ssh_timestamp_init(&ts);
    usleep(50000);
    assert_true(ssh_timeout_elapsed(&ts,25));
    assert_false(ssh_timeout_elapsed(&ts,30000));
    assert_false(ssh_timeout_elapsed(&ts,75));
    assert_true(ssh_timeout_elapsed(&ts,0));
    assert_false(ssh_timeout_elapsed(&ts,-1));
}
Ejemplo n.º 4
0
/**
 * @brief A wrapper for the select syscall
 *
 * This functions acts more or less like the select(2) syscall.\n
 * There is no support for writing or exceptions.\n
 *
 * @param[in]  channels Arrays of channels pointers terminated by a NULL.
 *                      It is never rewritten.
 *
 * @param[out] outchannels Arrays of same size that "channels", there is no need
 *                         to initialize it.
 *
 * @param[in]  maxfd    Maximum +1 file descriptor from readfds.
 *
 * @param[in]  readfds  A fd_set of file descriptors to be select'ed for
 *                      reading.
 *
 * @param[in]  timeout  A timeout for the select.
 *
 * @return              SSH_OK on success,
 *                      SSH_ERROR on error,
 *                      SSH_EINTR if it was interrupted. In that case,
 *                      just restart it.
 *
 * @warning libssh is not reentrant here. That means that if a signal is caught
 *          during the processing of this function, you cannot call libssh
 *          functions on sessions that are busy with ssh_select().
 *
 * @see select(2)
 */
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
    fd_set *readfds, struct timeval *timeout) {
  fd_set origfds;
  socket_t fd;
  int i,j;
  int rc;
  int base_tm, tm;
  struct ssh_timestamp ts;
  ssh_event event = ssh_event_new();
  int firstround=1;

  base_tm = tm=timeout->tv_sec * 1000 + timeout->tv_usec/1000;
  for (i=0 ; channels[i] != NULL; ++i){
    ssh_event_add_session(event, channels[i]->session);
  }

  FD_ZERO(&origfds);
  for (fd = 0; fd < maxfd ; fd++) {
      if (FD_ISSET(fd, readfds)) {
          ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
          FD_SET(fd, &origfds);
      }
  }
  outchannels[0] = NULL;
  FD_ZERO(readfds);
  ssh_timestamp_init(&ts);
  do {
    /* Poll every channel */
    j = 0;
    for (i = 0; channels[i]; i++) {
      if(ssh_channel_poll(channels[i], 0) != 0) {
        outchannels[j] = channels[i];
        j++;
      } else if(ssh_channel_poll(channels[i], 1) != 0) {
        outchannels[j] = channels[i];
        j++;
      }
    }
    outchannels[j] = NULL;
    if(j != 0)
      break;
    /* watch if a user socket was triggered */
    for (fd = 0; fd < maxfd; fd++) {
        if (FD_ISSET(fd, readfds)) {
            goto out;
        }
    }

    /* If the timeout is elapsed, we should go out */
    if(!firstround && ssh_timeout_elapsed(&ts, base_tm))
      goto out;
    /* since there's nothing, let's fire the polling */
    rc = ssh_event_dopoll(event,tm);
    if (rc == SSH_ERROR){
      goto out;
    }
    tm = ssh_timeout_update(&ts, base_tm);
    firstround=0;
  } while (1);
out:
  for (fd = 0; fd < maxfd; fd++) {
    if (FD_ISSET(fd, &origfds)) {
      ssh_event_remove_fd(event, fd);
    }
  }
  ssh_event_free(event);
  return SSH_OK;
}