1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-04 21:12:47 -05:00

Revamp of EOF handling in all network connections, pipes and other

data channels. Should comprehensively fix 'half-closed', in principle,
though it's a big and complicated change and so there's a good chance
I've made at least one mistake somewhere.

All connections should now be rigorous about propagating end-of-file
(or end-of-data-stream, or socket shutdown, or whatever) independently
in both directions, except in frontends with no mechanism for sending
explicit EOF (e.g. interactive terminal windows) or backends which are
basically always used for interactive sessions so it's unlikely that
an application would be depending on independent EOF (telnet, rlogin).

EOF should now never accidentally be sent while there's still buffered
data to go out before it. (May help fix 'portfwd-corrupt', and also I
noticed recently that the ssh main session channel can accidentally
have MSG_EOF sent before the output bufchain is clear, leading to
embarrassment when it subsequently does send the output).

[originally from svn r9279]
This commit is contained in:
Simon Tatham
2011-09-13 11:44:03 +00:00
parent c68a646c64
commit 947962e0b9
23 changed files with 616 additions and 237 deletions

View File

@ -29,6 +29,7 @@ struct Socket_localproxy_tag {
bufchain pending_output_data;
bufchain pending_input_data;
enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
void *privptr;
};
@ -95,12 +96,14 @@ static void sk_localproxy_close (Socket s)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
del234(localproxy_by_fromfd, ps);
del234(localproxy_by_tofd, ps);
if (ps->to_cmd >= 0) {
del234(localproxy_by_tofd, ps);
uxsel_del(ps->to_cmd);
close(ps->to_cmd);
}
uxsel_del(ps->to_cmd);
del234(localproxy_by_fromfd, ps);
uxsel_del(ps->from_cmd);
close(ps->to_cmd);
close(ps->from_cmd);
sfree(ps);
@ -129,6 +132,14 @@ static int localproxy_try_send(Local_Proxy_Socket ps)
}
}
if (ps->outgoingeof == EOF_PENDING) {
del234(localproxy_by_tofd, ps);
close(ps->to_cmd);
uxsel_del(ps->to_cmd);
ps->to_cmd = -1;
ps->outgoingeof = EOF_SENT;
}
if (bufchain_size(&ps->pending_output_data) == 0)
uxsel_del(ps->to_cmd);
else
@ -141,6 +152,8 @@ static int sk_localproxy_write (Socket s, const char *data, int len)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
assert(ps->outgoingeof == EOF_NO);
bufchain_add(&ps->pending_output_data, data, len);
localproxy_try_send(ps);
@ -157,6 +170,16 @@ static int sk_localproxy_write_oob (Socket s, const char *data, int len)
return sk_localproxy_write(s, data, len);
}
static void sk_localproxy_write_eof (Socket s)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
assert(ps->outgoingeof == EOF_NO);
ps->outgoingeof = EOF_PENDING;
localproxy_try_send(ps);
}
static void sk_localproxy_flush (Socket s)
{
/* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */
@ -233,6 +256,7 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
sk_localproxy_close,
sk_localproxy_write,
sk_localproxy_write_oob,
sk_localproxy_write_eof,
sk_localproxy_flush,
sk_localproxy_set_private_ptr,
sk_localproxy_get_private_ptr,
@ -252,6 +276,7 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
ret->fn = &socket_fn_table;
ret->plug = plug;
ret->error = NULL;
ret->outgoingeof = EOF_NO;
bufchain_init(&ret->pending_input_data);
bufchain_init(&ret->pending_output_data);