* 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
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 */
}
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);
}
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);
}
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;
}
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);
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);
}
}
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;
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);