/* {{{ libssh2_packet_requirev * Loops libssh2_packet_read() until one of a list of packet types requested is available * SSH_DISCONNECT or a SOCKET_DISCONNECTED will cause a bailout * packet_types is a null terminated list of packet_type numbers */ int libssh2_packet_requirev_ex(LIBSSH2_SESSION *session, unsigned char *packet_types, unsigned char **data, unsigned long *data_len, unsigned long match_ofs, const unsigned char *match_buf, unsigned long match_len) { if (libssh2_packet_askv_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0) == 0) { /* One of the packets listed was available in the packet brigade */ return 0; } while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) { int ret = libssh2_packet_read(session, 1); if (ret < 0) { return -1; } if (ret == 0) { continue; } if (strchr(packet_types, ret)) { /* Be lazy, let packet_ask pull it out of the brigade */ return libssh2_packet_askv_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0); } } /* Only reached if the socket died */ return -1; }
int libssh2_packet_requirev_ex(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_ex (session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0) == 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_packet_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) || (libssh2_waitsocket(session, 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_ex(session, packet_types, data, data_len, match_ofs, match_buf, match_len, 0); } } /* Only reached if the socket died */ state->start = 0; return -1; }
/* {{{ libssh2_packet_burn * Loops libssh2_packet_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; unsigned long data_len; unsigned char all_packets[255]; int i; int ret; if (*state == libssh2_NB_state_idle) { for(i = 1; i < 256; i++) { all_packets[i - 1] = i; } if (libssh2_packet_askv_ex (session, all_packets, &data, &data_len, 0, NULL, 0, 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_DBG_TRANS, "Blocking until packet becomes available to burn"); *state = libssh2_NB_state_created; } while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { if ((ret = libssh2_packet_read(session)) == PACKET_EAGAIN) { return PACKET_EAGAIN; } 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_ex(session, ret, &data, &data_len, 0, NULL, 0, 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 -1; }
/* {{{ libssh2_packet_burn * Loops libssh2_packet_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) { unsigned char *data; unsigned long data_len; char all_packets[255]; int i; for(i = 1; i < 256; i++) all_packets[i - 1] = i; if (libssh2_packet_askv_ex(session, all_packets, &data, &data_len, 0, NULL, 0, 0) == 0) { i = data[0]; /* A packet was available in the packet brigade, burn it */ LIBSSH2_FREE(session, data); return i; } #ifdef LIBSSH2_DEBUG_TRANSPORT _libssh2_debug(session, LIBSSH2_DBG_TRANS, "Blocking until packet becomes available to burn"); #endif while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { int ret = libssh2_packet_read(session, 1); if (ret < 0) { return -1; } if (ret == 0) continue; /* Be lazy, let packet_ask pull it out of the brigade */ if (0 == libssh2_packet_ask_ex(session, ret, &data, &data_len, 0, NULL, 0, 0)) { /* Smoke 'em if you got 'em */ LIBSSH2_FREE(session, data); return ret; } } /* Only reached if the socket died */ return -1; }