From: simon Date: Wed, 24 Jan 2001 10:11:18 +0000 (+0000) Subject: Improve socket error handling so that a socket error isn't an X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/commitdiff_plain/2c94fd1cbf32093be173ea6c4378caa109f73dd4 Improve socket error handling so that a socket error isn't an automatic fatalbox(). Instead, the error is passed to the receiver routine, which can decide just how fatal the problem really is. git-svn-id: svn://svn.tartarus.org/sgt/putty@894 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/network.h b/network.h index 46088002..528e92ab 100644 --- a/network.h +++ b/network.h @@ -8,10 +8,6 @@ * send data without having to worry about blocking. The stuff * behind the abstraction takes care of selects and nonblocking * writes and all that sort of painful gubbins. - * - * If urgent data comes in on a socket, the back end will read and - * discard up to the urgent pointer, then read the urgent byte and - * send _that_ to the receiver function with `urgent' set. */ #ifndef PUTTY_NETWORK_H @@ -19,6 +15,24 @@ typedef struct Socket_tag *Socket; typedef struct SockAddr_tag *SockAddr; + +/* + * This is the function a client must register with each socket, to + * receive data coming in on that socket. The parameter `urgent' + * decides the meaning of `data' and `len': + * + * - urgent==0. `data' points to `len' bytes of perfectly ordinary + * data. + * + * - urgent==1. `data' points to `len' bytes of data, which were + * read from before an Urgent pointer. + * + * - urgent==2. `data' points to `len' bytes of data, the first of + * which was the one at the Urgent mark. + * + * - urgent==3. An error has occurred on the socket. `data' points + * to an error string, and `len' points to an error code. + */ typedef int (*sk_receiver_t)(Socket s, int urgent, char *data, int len); void sk_init(void); /* called once at program startup */ diff --git a/raw.c b/raw.c index 61a7d668..c3545803 100644 --- a/raw.c +++ b/raw.c @@ -25,6 +25,11 @@ static void c_write (char *buf, int len) { } static int raw_receive (Socket s, int urgent, char *data, int len) { + if (urgent==3) { + /* A socket error has occurred. */ + connection_fatal(data); + len = 0; + } if (!len) { /* Connection has closed. */ sk_close(s); diff --git a/rlogin.c b/rlogin.c index b3e9eac9..c77f381f 100644 --- a/rlogin.c +++ b/rlogin.c @@ -25,6 +25,11 @@ static void c_write (char *buf, int len) { } static int rlogin_receive (Socket s, int urgent, char *data, int len) { + if (urgent==3) { + /* A socket error has occurred. */ + connection_fatal(data); + len = 0; + } if (!len) { /* Connection has closed. */ sk_close(s); diff --git a/ssh.c b/ssh.c index ee320afc..3845264c 100644 --- a/ssh.c +++ b/ssh.c @@ -1148,6 +1148,11 @@ static void ssh_gotdata(unsigned char *data, int datalen) } static int ssh_receive(Socket skt, int urgent, char *data, int len) { + if (urgent==3) { + /* A socket error has occurred. */ + connection_fatal(data); + len = 0; + } if (!len) { /* Connection has closed. */ ssh_state = SSH_STATE_CLOSED; diff --git a/telnet.c b/telnet.c index 67979120..f30902d2 100644 --- a/telnet.c +++ b/telnet.c @@ -461,6 +461,11 @@ static void do_telnet_read (char *buf, int len) { } static int telnet_receive(Socket s, int urgent, char *data, int len) { + if (urgent==3) { + /* A socket error has occurred. */ + connection_fatal(data); + len = 0; + } if (!len) { /* Connection has closed. */ sk_close(s); diff --git a/winnet.c b/winnet.c index 372845d5..fb276168 100644 --- a/winnet.c +++ b/winnet.c @@ -569,7 +569,11 @@ int select_result(WPARAM wParam, LPARAM lParam) { return 1; /* boggle */ if ((err = WSAGETSELECTERROR(lParam)) != 0) { - fatalbox(winsock_error_string(err)); + /* + * An error has occurred on this socket. Pass it to the + * receiver function. + */ + return s->receiver(s, 3, winsock_error_string(err), err); } noise_ultralight(lParam); @@ -584,7 +588,7 @@ int select_result(WPARAM wParam, LPARAM lParam) { } } if (ret < 0) { - fatalbox(winsock_error_string(err)); + return s->receiver(s, 3, winsock_error_string(err), err); } else { int type = s->in_oob ? 2 : 0; s->in_oob = FALSE; diff --git a/x11fwd.c b/x11fwd.c index b4fecd9a..7e995239 100644 --- a/x11fwd.c +++ b/x11fwd.c @@ -106,6 +106,14 @@ static int x11_verify(char *proto, unsigned char *data, int dlen) { static int x11_receive (Socket s, int urgent, char *data, int len) { struct X11Private *pr = (struct X11Private *)sk_get_private_ptr(s); + if (urgent==3) { + /* + * A socket error has occurred. We have no way to + * communicate this down the forwarded connection, so we'll + * just treat it like a proper close. + */ + len = 0; + } if (!len) { /* Connection has closed. */ sshfwd_close(pr->c);