Пример #1
0
/*
 * _libssh2_packet_burn
 *
 * Loops _libssh2_transport_read() until any packet is available and promptly
 * discards it.
 * Used during KEX exchange to discard badly guessed KEX_INIT packets
 */
int
_libssh2_packet_burn(LIBSSH2_SESSION * session,
                     libssh2_nonblocking_states * state)
{
    unsigned char *data;
    size_t data_len;
    unsigned char i, all_packets[255];
    int ret;

    if (*state == libssh2_NB_state_idle) {
        for(i = 1; i < 255; i++) {
            all_packets[i - 1] = i;
        }
        all_packets[254] = 0;

        if (_libssh2_packet_askv(session, all_packets, &data, &data_len, 0,
                                 NULL, 0) == 0) {
            i = data[0];
            /* A packet was available in the packet brigade, burn it */
            LIBSSH2_FREE(session, data);
            return i;
        }

        _libssh2_debug(session, LIBSSH2_TRACE_TRANS,
                       "Blocking until packet becomes available to burn");
        *state = libssh2_NB_state_created;
    }

    while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
        ret = _libssh2_transport_read(session);
        if (ret == LIBSSH2_ERROR_EAGAIN) {
            return ret;
        } else if (ret < 0) {
            *state = libssh2_NB_state_idle;
            return ret;
        } else if (ret == 0) {
            /* FIXME: this might busyloop */
            continue;
        }

        /* Be lazy, let packet_ask pull it out of the brigade */
        if (0 ==
            _libssh2_packet_ask(session, (unsigned char)ret,
                                         &data, &data_len, 0, NULL, 0)) {
            /* Smoke 'em if you got 'em */
            LIBSSH2_FREE(session, data);
            *state = libssh2_NB_state_idle;
            return ret;
        }
    }

    /* Only reached if the socket died */
    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}
Пример #2
0
int
_libssh2_packet_requirev(LIBSSH2_SESSION * session,
                         const unsigned char *packet_types,
                         unsigned char **data, unsigned long *data_len,
                         unsigned long match_ofs,
                         const unsigned char *match_buf,
                         unsigned long match_len,
                         packet_requirev_state_t * state)
{
    if (_libssh2_packet_askv(session, packet_types, data, data_len, match_ofs,
                             match_buf, match_len) == 0) {
        /* One of the packets listed was available in the packet brigade */
        state->start = 0;
        return 0;
    }

    if (state->start == 0) {
        state->start = time(NULL);
    }

    while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) {
        int ret = _libssh2_transport_read(session);
        if ((ret < 0) && (ret != PACKET_EAGAIN)) {
            state->start = 0;
            return ret;
        }
        if (ret <= 0) {
            long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);

            if (left <= 0) {
                state->start = 0;
                return PACKET_TIMEOUT;
            }
            else if (ret == PACKET_EAGAIN) {
                return PACKET_EAGAIN;
            }
        }

        if (strchr((char *) packet_types, ret)) {
            /* Be lazy, let packet_ask pull it out of the brigade */
            return _libssh2_packet_askv(session, packet_types, data,
                                        data_len, match_ofs, match_buf,
                                        match_len);
        }
    }

    /* Only reached if the socket died */
    state->start = 0;
    return -1;
}
Пример #3
0
/*
 * _libssh2_packet_require
 *
 * Loops _libssh2_transport_read() until the packet requested is available
 * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
 *
 * Returns negative on error
 * Returns 0 when it has taken care of the requested packet.
 */
int
_libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
                        unsigned char **data, unsigned long *data_len,
                        unsigned long match_ofs,
                        const unsigned char *match_buf,
                        unsigned long match_len,
                        packet_require_state_t *state)
{
    if (state->start == 0) {
        if (_libssh2_packet_ask(session, packet_type, data, data_len,
                               match_ofs, match_buf,
                               match_len) == 0) {
            /* A packet was available in the packet brigade */
            return 0;
        }

        state->start = time(NULL);
    }

    while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
        libssh2pack_t ret = _libssh2_transport_read(session);
        if (ret == PACKET_EAGAIN) {
            return PACKET_EAGAIN;
        } else if (ret == 0) {
            /* There is no data, return that. TODO: is this really correct? */
            return PACKET_EAGAIN;
        } else if (ret < 0) {
            state->start = 0;
            /* an error which is not just because of blocking */
            return ret;
        } else if (ret == packet_type) {
            /* Be lazy, let packet_ask pull it out of the brigade */
            ret = _libssh2_packet_ask(session, packet_type, data, data_len,
                                     match_ofs, match_buf, match_len);
            state->start = 0;
            return ret;
        } else if (ret == 0) {
            /* nothing available, wait until data arrives or we time out */
            long left = LIBSSH2_READ_TIMEOUT - (time(NULL) - state->start);

            if (left <= 0) {
                state->start = 0;
                return PACKET_TIMEOUT;
            }
        }
    }

    /* Only reached if the socket died */
    return -1;
}
Пример #4
0
/*
 * _libssh2_packet_require
 *
 * Loops _libssh2_transport_read() until the packet requested is available
 * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout
 *
 * Returns negative on error
 * Returns 0 when it has taken care of the requested packet.
 */
int
_libssh2_packet_require(LIBSSH2_SESSION * session, unsigned char packet_type,
                        unsigned char **data, size_t *data_len,
                        int match_ofs,
                        const unsigned char *match_buf,
                        size_t match_len,
                        packet_require_state_t *state)
{
    if (state->start == 0) {
        if (_libssh2_packet_ask(session, packet_type, data, data_len,
                                match_ofs, match_buf,
                                match_len) == 0) {
            /* A packet was available in the packet brigade */
            return 0;
        }

        state->start = time(NULL);
    }

    while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) {
        int ret = _libssh2_transport_read(session);
        if (ret == LIBSSH2_ERROR_EAGAIN)
            return ret;
        else if (ret < 0) {
            state->start = 0;
            /* an error which is not just because of blocking */
            return ret;
        } else if (ret == packet_type) {
            /* Be lazy, let packet_ask pull it out of the brigade */
            ret = _libssh2_packet_ask(session, packet_type, data, data_len,
                                      match_ofs, match_buf, match_len);
            state->start = 0;
            return ret;
        } else if (ret == 0) {
            /* nothing available, wait until data arrives or we time out */
            long left = LIBSSH2_READ_TIMEOUT - (long)(time(NULL) -
                                                      state->start);

            if (left <= 0) {
                state->start = 0;
                return LIBSSH2_ERROR_TIMEOUT;
            }
            return -1; /* no packet available yet */
        }
    }

    /* Only reached if the socket died */
    return LIBSSH2_ERROR_SOCKET_DISCONNECT;
}