/*
* Codes for terminal modes.
* Most of these are the same in SSH-1 and SSH-2.
- * This list is derived from draft-ietf-secsh-connect-25 and
+ * This list is derived from RFC 4254 and
* SSH-1 RFC-1.2.31.
*/
static const struct {
*
* - 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. It must be <= INT_MAX.
*/
#define SSH1_BUFFER_LIMIT 32768
#define SSH_MAX_BACKLOG 32768
#define OUR_V2_WINSIZE 16384
+#define OUR_V2_BIGWIN 0x7fffffff
#define OUR_V2_MAXPKT 0x4000UL
/* Maximum length of passwords/passphrases (arbitrary) */
bufchain outbuffer;
unsigned remwindow, remmaxpkt;
/* locwindow is signed so we can cope with excess data. */
- int locwindow;
+ int locwindow, locmaxwin;
} v2;
} v;
union {
static int ssh2_try_send(struct ssh_channel *c);
static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);
static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
-static void ssh2_set_window(struct ssh_channel *c, unsigned newwin);
+static void ssh2_set_window(struct ssh_channel *c, int newwin);
static int ssh_sendbuffer(void *handle);
static int ssh_do_close(Ssh ssh, int notify_exit);
static unsigned long ssh_pkt_getuint32(struct Packet *pkt);
ssh1_throttle(ssh, -1);
}
} else {
- ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
+ ssh2_set_window(c, c->v.v2.locmaxwin - bufsize);
}
}
/*
* Potentially enlarge the window on an SSH-2 channel.
*/
-static void ssh2_set_window(struct ssh_channel *c, unsigned newwin)
+static void ssh2_set_window(struct ssh_channel *c, int newwin)
{
Ssh ssh = c->ssh;
*
* "Significant" is arbitrarily defined as half the window size.
*/
- if (newwin > c->v.v2.locwindow * 2) {
+ if (newwin / 2 >= c->v.v2.locwindow) {
struct Packet *pktout;
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
* need to adjust the window if the server's
* sent excess data.
*/
- ssh2_set_window(c, bufsize < OUR_V2_WINSIZE ?
- OUR_V2_WINSIZE - bufsize : 0);
+ ssh2_set_window(c, bufsize < c->v.v2.locmaxwin ?
+ c->v.v2.locmaxwin - bufsize : 0);
}
}
} 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);
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);
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);
ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] =
ssh2_msg_channel_open;
+ if (ssh->cfg.ssh_simple) {
+ /*
+ * This message indicates to the server that we promise
+ * not to try to run any other channel in parallel with
+ * this one, so it's safe for it to advertise a very large
+ * window and leave the flow control to TCP.
+ */
+ s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
+ ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
+ ssh2_pkt_addstring(s->pktout, "simple@putty.projects.tartarus.org");
+ ssh2_pkt_addbool(s->pktout, 0); /* no reply */
+ ssh2_pkt_send(ssh, s->pktout);
+ }
+
/*
* Potentially enable X11 forwarding.
*/
ssh1_throttle(ssh, -1);
}
} else {
- ssh2_set_window(ssh->mainchan, OUR_V2_WINSIZE - bufsize);
+ if (ssh->mainchan)
+ ssh2_set_window(ssh->mainchan,
+ ssh->mainchan->v.v2.locmaxwin - bufsize);
}
}
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);