From 81bdcf61f38f4a3e532c17d915b2b32a27bee52b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 8 Sep 2011 14:25:25 +0200 Subject: [PATCH] _libssh2_channel_read: fix non-blocking window adjusting If EAGAIN is returned when adjusting the receive window, we must not read from the transport directly until we've finished the adjusting. --- src/channel.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/channel.c b/src/channel.c index be6a680..75b47a5 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1754,6 +1754,16 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, stream_id); channel->read_state = libssh2_NB_state_created; } + + /* + * =============================== NOTE =============================== + * I know this is very ugly and not a really good use of "goto", but + * this case statement would be even uglier to do it any other way + */ + if (channel->read_state == libssh2_NB_state_jump1) { + goto channel_read_window_adjust; + } + rc = 1; /* set to >0 to let the while loop start */ /* Process all pending incoming packets in all states in order to "even @@ -1765,15 +1775,6 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) return _libssh2_error(session, rc, "transport read"); - /* - * =============================== NOTE =============================== - * I know this is very ugly and not a really good use of "goto", but - * this case statement would be even uglier to do it any other way - */ - if (channel->read_state == libssh2_NB_state_jump1) { - goto channel_read_ex_point1; - } - read_packet = _libssh2_list_first(&session->packets); while (read_packet && (bytes_read < (int) buflen)) { /* previously this loop condition also checked for @@ -1874,7 +1875,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id, if(channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)) { /* the window is getting too narrow, expand it! */ - channel_read_ex_point1: + channel_read_window_adjust: channel->read_state = libssh2_NB_state_jump1; /* the actual window adjusting may not finish so we need to deal with this special state here */