};
/*
- * little structure to keep track of outstanding WINDOW_ADJUSTs
- */
-struct winadj {
- struct winadj *next;
- unsigned size;
-};
-
-/*
* 2-3-4 tree storing channels.
*/
struct ssh_channel {
unsigned char *message;
unsigned char msglen[4];
unsigned lensofar, totallen;
+ int outstanding_requests;
} a;
struct ssh_x11_channel {
Socket s;
Ssh ssh = c->ssh;
void *sentreply = reply;
+ c->u.a.outstanding_requests--;
if (!sentreply) {
/* Fake SSH_AGENT_FAILURE. */
sentreply = "\0\0\0\1\5";
}
if (reply)
sfree(reply);
+ /*
+ * If we've already seen an incoming EOF but haven't sent an
+ * outgoing one, this may be the moment to send it.
+ */
+ if (c->u.a.outstanding_requests == 0 && (c->closes & CLOSES_RCVD_EOF))
+ sshfwd_write_eof(c);
}
/*
c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0;
c->u.a.message = NULL;
+ c->u.a.outstanding_requests = 0;
add234(ssh->channels, c);
send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
PKT_INT, c->remoteid, PKT_INT, c->localid,
if (c->u.a.lensofar == c->u.a.totallen) {
void *reply;
int replylen;
+ c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message,
c->u.a.totallen,
&reply, &replylen,
}
/*
+ * Construct the common parts of a CHANNEL_OPEN.
+ */
+static struct Packet *ssh2_chanopen_init(struct ssh_channel *c, char *type)
+{
+ struct Packet *pktout;
+
+ pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
+ ssh2_pkt_addstring(pktout, type);
+ ssh2_pkt_adduint32(pktout, c->localid);
+ ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
+ ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
+ return pktout;
+}
+
+/*
* CHANNEL_FAILURE doesn't come with any indication of what message
* caused it, so we have to keep track of the outstanding
* CHANNEL_REQUESTs ourselves.
if (c->u.a.lensofar == c->u.a.totallen) {
void *reply;
int replylen;
+ c->u.a.outstanding_requests++;
if (agent_query(c->u.a.message,
c->u.a.totallen,
&reply, &replylen,
if (c->type == CHAN_X11) {
x11_send_eof(c->u.x11.s);
} else if (c->type == CHAN_AGENT) {
- /* Manufacture an outgoing EOF in response to the incoming one. */
- sshfwd_write_eof(c);
+ if (c->u.a.outstanding_requests == 0) {
+ /* Manufacture an outgoing EOF in response to the incoming one. */
+ sshfwd_write_eof(c);
+ }
} else if (c->type == CHAN_SOCKDATA) {
pfd_send_eof(c->u.pfd.s);
} else if (c->type == CHAN_MAINSESSION) {
else {
c->type = CHAN_AGENT; /* identify channel type */
c->u.a.lensofar = 0;
+ c->u.a.outstanding_requests = 0;
}
} else {
error = "Unsupported channel type requested";
"Opening direct-tcpip channel to %s:%d in place of session",
conf_get_str(ssh->conf, CONF_ssh_nc_host),
conf_get_int(ssh->conf, CONF_ssh_nc_port));
- s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
- ssh2_pkt_addstring(s->pktout, "direct-tcpip");
- ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
- 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 */
+ s->pktout = ssh2_chanopen_init(ssh->mainchan, "direct-tcpip");
ssh2_pkt_addstring(s->pktout, conf_get_str(ssh->conf, CONF_ssh_nc_host));
ssh2_pkt_adduint32(s->pktout, conf_get_int(ssh->conf, CONF_ssh_nc_port));
/*
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
ssh2_channel_init(ssh->mainchan);
- s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
- ssh2_pkt_addstring(s->pktout, "session");
- ssh2_pkt_adduint32(s->pktout, ssh->mainchan->localid);
- 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 */
+ s->pktout = ssh2_chanopen_init(ssh->mainchan, "session");
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
/* PKT_STR, <org:orgport>, */
PKT_END);
} else {
- pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
- ssh2_pkt_addstring(pktout, "direct-tcpip");
- ssh2_pkt_adduint32(pktout, c->localid);
- ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);/* our window size */
- ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
+ pktout = ssh2_chanopen_init(c, "direct-tcpip");
ssh2_pkt_addstring(pktout, hostname);
ssh2_pkt_adduint32(pktout, port);
/*