mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 09:58:01 +00:00
Robustness in the face of sudden connection closures: we now make a
credible effort to shut down open forwardings cleanly when the owning SSH connection terminates abruptly (for whatever reason). [originally from svn r3137]
This commit is contained in:
parent
51fa8d6294
commit
2a0fff2451
60
ssh.c
60
ssh.c
@ -515,6 +515,7 @@ 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 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, unsigned newwin);
|
||||||
static int ssh_sendbuffer(void *handle);
|
static int ssh_sendbuffer(void *handle);
|
||||||
|
static void ssh_do_close(Ssh ssh);
|
||||||
|
|
||||||
struct rdpkt1_state_tag {
|
struct rdpkt1_state_tag {
|
||||||
long len, pad, biglen, to_read;
|
long len, pad, biglen, to_read;
|
||||||
@ -668,8 +669,7 @@ static void logeventf(Ssh ssh, char *fmt, ...)
|
|||||||
#define bombout(msg) \
|
#define bombout(msg) \
|
||||||
do { \
|
do { \
|
||||||
char *text = dupprintf msg; \
|
char *text = dupprintf msg; \
|
||||||
ssh->state = SSH_STATE_CLOSED; \
|
ssh_do_close(ssh); \
|
||||||
if (ssh->s) { sk_close(ssh->s); ssh->s = NULL; } \
|
|
||||||
logevent(text); \
|
logevent(text); \
|
||||||
connection_fatal(ssh->frontend, "%s", text); \
|
connection_fatal(ssh->frontend, "%s", text); \
|
||||||
sfree(text); \
|
sfree(text); \
|
||||||
@ -2037,15 +2037,41 @@ static void ssh_gotdata(Ssh ssh, unsigned char *data, int datalen)
|
|||||||
crFinishV;
|
crFinishV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ssh_closing(Plug plug, char *error_msg, int error_code,
|
static void ssh_do_close(Ssh ssh)
|
||||||
int calling_back)
|
|
||||||
{
|
{
|
||||||
Ssh ssh = (Ssh) plug;
|
int i;
|
||||||
|
struct ssh_channel *c;
|
||||||
|
|
||||||
ssh->state = SSH_STATE_CLOSED;
|
ssh->state = SSH_STATE_CLOSED;
|
||||||
if (ssh->s) {
|
if (ssh->s) {
|
||||||
sk_close(ssh->s);
|
sk_close(ssh->s);
|
||||||
ssh->s = NULL;
|
ssh->s = NULL;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Now we must shut down any port and X forwardings going
|
||||||
|
* through this connection.
|
||||||
|
*/
|
||||||
|
for (i = 0; NULL != (c = index234(ssh->channels, i)); i++) {
|
||||||
|
switch (c->type) {
|
||||||
|
case CHAN_X11:
|
||||||
|
x11_close(c->u.x11.s);
|
||||||
|
break;
|
||||||
|
case CHAN_SOCKDATA:
|
||||||
|
pfd_close(c->u.pfd.s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
del234(ssh->channels, c);
|
||||||
|
if (ssh->version == 2)
|
||||||
|
bufchain_clear(&c->v.v2.outbuffer);
|
||||||
|
sfree(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ssh_closing(Plug plug, char *error_msg, int error_code,
|
||||||
|
int calling_back)
|
||||||
|
{
|
||||||
|
Ssh ssh = (Ssh) plug;
|
||||||
|
ssh_do_close(ssh);
|
||||||
if (error_msg) {
|
if (error_msg) {
|
||||||
/* A socket error has occurred. */
|
/* A socket error has occurred. */
|
||||||
logevent(error_msg);
|
logevent(error_msg);
|
||||||
@ -2061,10 +2087,7 @@ static int ssh_receive(Plug plug, int urgent, char *data, int len)
|
|||||||
Ssh ssh = (Ssh) plug;
|
Ssh ssh = (Ssh) plug;
|
||||||
ssh_gotdata(ssh, (unsigned char *)data, len);
|
ssh_gotdata(ssh, (unsigned char *)data, len);
|
||||||
if (ssh->state == SSH_STATE_CLOSED) {
|
if (ssh->state == SSH_STATE_CLOSED) {
|
||||||
if (ssh->s) {
|
ssh_do_close(ssh);
|
||||||
sk_close(ssh->s);
|
|
||||||
ssh->s = NULL;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -2180,7 +2203,7 @@ static void ssh_throttle_all(Ssh ssh, int enable, int bufsize)
|
|||||||
/* Agent channels require no buffer management. */
|
/* Agent channels require no buffer management. */
|
||||||
break;
|
break;
|
||||||
case CHAN_SOCKDATA:
|
case CHAN_SOCKDATA:
|
||||||
pfd_override_throttle(c->u.x11.s, enable);
|
pfd_override_throttle(c->u.pfd.s, enable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2992,6 +3015,11 @@ void sshfwd_close(struct ssh_channel *c)
|
|||||||
{
|
{
|
||||||
Ssh ssh = c->ssh;
|
Ssh ssh = c->ssh;
|
||||||
|
|
||||||
|
if (ssh->state != SSH_STATE_SESSION) {
|
||||||
|
assert(ssh->state == SSH_STATE_CLOSED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (c && !c->closes) {
|
if (c && !c->closes) {
|
||||||
/*
|
/*
|
||||||
* If the channel's remoteid is -1, we have sent
|
* If the channel's remoteid is -1, we have sent
|
||||||
@ -3026,6 +3054,11 @@ int sshfwd_write(struct ssh_channel *c, char *buf, int len)
|
|||||||
{
|
{
|
||||||
Ssh ssh = c->ssh;
|
Ssh ssh = c->ssh;
|
||||||
|
|
||||||
|
if (ssh->state != SSH_STATE_SESSION) {
|
||||||
|
assert(ssh->state == SSH_STATE_CLOSED);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ssh->version == 1) {
|
if (ssh->version == 1) {
|
||||||
send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
|
send_packet(ssh, SSH1_MSG_CHANNEL_DATA,
|
||||||
PKT_INT, c->remoteid,
|
PKT_INT, c->remoteid,
|
||||||
@ -3048,6 +3081,11 @@ void sshfwd_unthrottle(struct ssh_channel *c, int bufsize)
|
|||||||
{
|
{
|
||||||
Ssh ssh = c->ssh;
|
Ssh ssh = c->ssh;
|
||||||
|
|
||||||
|
if (ssh->state != SSH_STATE_SESSION) {
|
||||||
|
assert(ssh->state == SSH_STATE_CLOSED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (ssh->version == 1) {
|
if (ssh->version == 1) {
|
||||||
if (c->v.v1.throttling && bufsize < SSH1_BUFFER_LIMIT) {
|
if (c->v.v1.throttling && bufsize < SSH1_BUFFER_LIMIT) {
|
||||||
c->v.v1.throttling = 0;
|
c->v.v1.throttling = 0;
|
||||||
@ -6141,7 +6179,7 @@ static void ssh_free(void *handle)
|
|||||||
sfree(ssh->do_ssh2_authconn_state);
|
sfree(ssh->do_ssh2_authconn_state);
|
||||||
|
|
||||||
if (ssh->s)
|
if (ssh->s)
|
||||||
sk_close(ssh->s);
|
ssh_do_close(ssh);
|
||||||
sfree(ssh);
|
sfree(ssh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user