In the file-transfer applications, which only ever use the main
[u/mdw/putty] / ssh.c
diff --git a/ssh.c b/ssh.c
index 3476d3d..51b5320 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -470,11 +470,15 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
  * 
  *  - OUR_V2_WINSIZE is the maximum window size we present on SSH-2
  *    channels.
+ *
+ *  - OUR_V2_BIGWIN is the window size we advertise for the only
+ *    channel in a simple connection.
  */
 
 #define SSH1_BUFFER_LIMIT 32768
 #define SSH_MAX_BACKLOG 32768
 #define OUR_V2_WINSIZE 16384
+#define OUR_V2_BIGWIN 0x10000000
 #define OUR_V2_MAXPKT 0x4000UL
 
 /* Maximum length of passwords/passphrases (arbitrary) */
@@ -551,7 +555,8 @@ struct ssh_channel {
        struct ssh2_data_channel {
            bufchain outbuffer;
            unsigned remwindow, remmaxpkt;
-           unsigned locwindow;
+           /* locwindow is signed so we can cope with excess data. */
+           int locwindow, locmaxwin;
        } v2;
     } v;
     union {
@@ -1221,9 +1226,9 @@ static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
            /* "Session data" packets - omit the data field */
            if ((st->pktin->type == SSH1_SMSG_STDOUT_DATA) ||
                (st->pktin->type == SSH1_SMSG_STDERR_DATA)) {
-               do_blank = TRUE; blank_prefix = 0;
-           } else if (st->pktin->type == SSH1_MSG_CHANNEL_DATA) {
                do_blank = TRUE; blank_prefix = 4;
+           } else if (st->pktin->type == SSH1_MSG_CHANNEL_DATA) {
+               do_blank = TRUE; blank_prefix = 8;
            }
            if (do_blank) {
                blank.offset = blank_prefix;
@@ -1381,9 +1386,9 @@ static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
            int do_blank = FALSE, blank_prefix = 0;
            /* "Session data" packets - omit the data field */
            if (st->pktin->type == SSH2_MSG_CHANNEL_DATA) {
-               do_blank = TRUE; blank_prefix = 4;
-           } else if (st->pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
                do_blank = TRUE; blank_prefix = 8;
+           } else if (st->pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
+               do_blank = TRUE; blank_prefix = 12;
            }
            if (do_blank) {
                blank.offset = blank_prefix;
@@ -2939,8 +2944,8 @@ static void ssh_agentf_callback(void *cv, void *reply, int replylen)
     } else {
        send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
                    PKT_INT, c->remoteid,
-                   PKTT_DATA,
                    PKT_INT, replylen,
+                   PKTT_DATA,
                    PKT_DATA, sentreply, replylen,
                    PKTT_OTHER,
                    PKT_END);
@@ -4000,8 +4005,7 @@ int sshfwd_write(struct ssh_channel *c, char *buf, int len)
     if (ssh->version == 1) {
        send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
                    PKT_INT, c->remoteid,
-                   PKTT_DATA,
-                   PKT_INT, len, PKT_DATA, buf, len,
+                   PKT_INT, len, PKTT_DATA, PKT_DATA, buf, len,
                    PKTT_OTHER, PKT_END);
        /*
         * In SSH-1 we can return 0 here - implying that forwarded
@@ -4030,7 +4034,7 @@ void sshfwd_unthrottle(struct ssh_channel *c, int bufsize)
            ssh1_throttle(ssh, -1);
        }
     } else {
-       ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
+       ssh2_set_window(c, c->v.v2.locmaxwin - bufsize);
     }
 }
 
@@ -4972,8 +4976,8 @@ static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
        } else {
            while (inlen > 0) {
                int len = min(inlen, 512);
-               send_packet(ssh, SSH1_CMSG_STDIN_DATA, PKTT_DATA,
-                           PKT_INT, len, PKT_DATA, in, len,
+               send_packet(ssh, SSH1_CMSG_STDIN_DATA,
+                           PKT_INT, len,  PKTT_DATA, PKT_DATA, in, len,
                            PKTT_OTHER, PKT_END);
                in += len;
                inlen -= len;
@@ -6123,8 +6127,8 @@ static int ssh2_try_send(struct ssh_channel *c)
            len = c->v.v2.remmaxpkt;
        pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_DATA);
        ssh2_pkt_adduint32(pktout, c->remoteid);
-       dont_log_data(ssh, pktout, PKTLOG_OMIT);
        ssh2_pkt_addstring_start(pktout);
+       dont_log_data(ssh, pktout, PKTLOG_OMIT);
        ssh2_pkt_addstring_data(pktout, data, len);
        end_log_omission(ssh, pktout);
        ssh2_pkt_send(ssh, pktout);
@@ -6187,7 +6191,7 @@ static void ssh2_set_window(struct ssh_channel *c, unsigned newwin)
      *
      * "Significant" is arbitrarily defined as half the window size.
      */
-    if (newwin > c->v.v2.locwindow * 2) {
+    if (newwin >= c->v.v2.locwindow * 2) {
        struct Packet *pktout;
 
        pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
@@ -6284,9 +6288,12 @@ static void ssh2_msg_channel_data(Ssh ssh, struct Packet *pktin)
        /*
         * If we are not buffering too much data,
         * enlarge the window again at the remote side.
+        * If we are buffering too much, we may still
+        * need to adjust the window if the server's
+        * sent excess data.
         */
-       if (bufsize < OUR_V2_WINSIZE)
-           ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
+       ssh2_set_window(c, bufsize < c->v.v2.locmaxwin ?
+                       c->v.v2.locmaxwin - bufsize : 0);
     }
 }
 
@@ -6753,7 +6760,7 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
     } else {
        c->localid = alloc_channel_id(ssh);
        c->closes = 0;
-       c->v.v2.locwindow = OUR_V2_WINSIZE;
+       c->v.v2.locwindow = c->v.v2.locmaxwin = OUR_V2_WINSIZE;
        c->v.v2.remwindow = winsize;
        c->v.v2.remmaxpkt = pktsize;
        bufchain_init(&c->v.v2.outbuffer);
@@ -7964,7 +7971,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
        s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
        ssh2_pkt_addstring(s->pktout, "direct-tcpip");
        ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
-       ssh->mainchan->v.v2.locwindow = OUR_V2_WINSIZE;
+       ssh->mainchan->v.v2.locwindow = ssh->mainchan->v.v2.locmaxwin =
+           ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
        ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
        ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT);      /* our max pkt size */
        ssh2_pkt_addstring(s->pktout, ssh->cfg.ssh_nc_host);
@@ -8006,7 +8014,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
        s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
        ssh2_pkt_addstring(s->pktout, "session");
        ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
-       ssh->mainchan->v.v2.locwindow = OUR_V2_WINSIZE;
+       ssh->mainchan->v.v2.locwindow = ssh->mainchan->v.v2.locmaxwin =
+           ssh->cfg.ssh_simple ? OUR_V2_BIGWIN : OUR_V2_WINSIZE;
        ssh2_pkt_adduint32(s->pktout, ssh->mainchan->v.v2.locwindow);/* our window size */
        ssh2_pkt_adduint32(s->pktout, OUR_V2_MAXPKT);    /* our max pkt size */
        ssh2_pkt_send(ssh, s->pktout);
@@ -9059,7 +9068,8 @@ static void ssh_unthrottle(void *handle, int bufsize)
            ssh1_throttle(ssh, -1);
        }
     } else {
-       ssh2_set_window(ssh->mainchan, OUR_V2_WINSIZE - bufsize);
+       ssh2_set_window(ssh->mainchan,
+                       ssh->mainchan->v.v2.locmaxwin - bufsize);
     }
 }
 
@@ -9082,7 +9092,7 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org)
        pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
        ssh2_pkt_addstring(pktout, "direct-tcpip");
        ssh2_pkt_adduint32(pktout, c->localid);
-       c->v.v2.locwindow = OUR_V2_WINSIZE;
+       c->v.v2.locwindow = c->v.v2.locmaxwin = OUR_V2_WINSIZE;
        ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
        ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT);      /* our max pkt size */
        ssh2_pkt_addstring(pktout, hostname);