Subject: [PATCH] Adjust the receive window correctly

[PATCH] Adjust the receive window correctly

From: liuzl <xieepp_at_gmail.com>
Date: Wed, 31 Aug 2011 20:40:59 +0800

Handle the error code LIBSSH2_ERROR_BAD_USE correctly,
avoid the receive window reduce to zero.

Signed-off-by: liuzl <xieepp_at_gmail.com>

---
 src/channel.c |   54 +++++++++++++++++++++++++-----------------------------
 1 files changed, 25 insertions(+), 29 deletions(-)
diff --git a/src/channel.c b/src/channel.c
index be6a680..2cbe934 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1585,8 +1585,7 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
         return rc;
     }
     else if (rc) {
-        channel->adjust_queue = adjustment;
-        return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
+        return _libssh2_error(channel->session, rc,
                               "Unable to send transfer-window adjustment "
                               "packet, deferring");
     }
@@ -1765,13 +1764,12 @@ 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;
+    if (channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)
+            && channel->adjust_state == libssh2_NB_state_idle) {
+        /* the window is getting too narrow, expand it!
+        Ignore all the sending errors since we are receiving. */
+        _libssh2_channel_receive_window_adjust(channel,
+            (LIBSSH2_CHANNEL_WINDOW_DEFAULT*60), 0, NULL);
     }
 
     read_packet = _libssh2_list_first(&session->packets);
@@ -1871,26 +1869,6 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
            more off the network again */
         channel->read_state = libssh2_NB_state_created;
 
-    if(channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)) {
-        /* the window is getting too narrow, expand it! */
-
-      channel_read_ex_point1:
-        channel->read_state = libssh2_NB_state_jump1;
-        /* the actual window adjusting may not finish so we need to deal with
-           this special state here */
-        rc = _libssh2_channel_receive_window_adjust(channel,
-                                                    (LIBSSH2_CHANNEL_WINDOW_DEFAULT*60), 0, NULL);
-        if (rc == LIBSSH2_ERROR_EAGAIN)
-            return rc;
-
-        _libssh2_debug(session, LIBSSH2_TRACE_CONN,
-                       "channel_read() filled %d adjusted %d",
-                       bytes_read, buflen);
-        /* continue in 'created' state to drain the already read packages
-           first before starting to empty the socket further */
-        channel->read_state = libssh2_NB_state_created;
-    }
-
     return bytes_read;
 }
 
@@ -1996,6 +1974,24 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
     if(buflen > 32700)
         buflen = 32700;
 
+    /* The previous receive window adjust failed, try again. */
+    if (channel->adjust_state == libssh2_NB_state_created) {
+        /* Adjust the receive window size as soon as we can. */
+        rc = _libssh2_channel_receive_window_adjust(channel,
+            (LIBSSH2_CHANNEL_WINDOW_DEFAULT*60), 0, NULL);
+
+        /* Logic error, we will try again next time. */
+        if (rc == LIBSSH2_ERROR_BAD_USE) {
+            _libssh2_error(channel->session, rc,
+                "Unable to send transfer-window adjustment packet in "
+                "_libssh2_channel_write(), deferring");
+        }
+        /* Block or really socket error. */
+        else if (rc < 0){
+            return rc;
+        }
+    }
+
     if (channel->write_state == libssh2_NB_state_idle) {
         unsigned char *s = channel->write_packet;
 
-- 
1.7.4.msysgit.0
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2011-08-31