From 4b1e8accb59e8f3b35d24f7ae207325a49cb3cc6 Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 1 Feb 2001 14:11:04 +0000 Subject: [PATCH] Yet another attempt at OOB handling in the network abstraction. This version allows you to specify, per socket, which sockets receive OOB data in-line (so that you know what was before the mark and what was after) and which receive it out of line (so it's really a one-byte out-of-band facility rather than discard-to-mark). This reflects the fact that rlogin appears to make more sense in the latter mode, and telnet in the former. This patch makes rlogin work right for me. git-svn-id: svn://svn.tartarus.org/sgt/putty@921 cda61777-01e9-0310-a592-d414129be87e --- network.h | 3 ++- raw.c | 2 +- rlogin.c | 2 +- ssh.c | 2 +- telnet.c | 2 +- winnet.c | 51 +++++++++++++++++++++++++++++++++------------------ x11fwd.c | 2 +- 7 files changed, 40 insertions(+), 24 deletions(-) diff --git a/network.h b/network.h index 528e92ab..ba1e1df8 100644 --- a/network.h +++ b/network.h @@ -40,7 +40,8 @@ void sk_init(void); /* called once at program startup */ SockAddr sk_namelookup(char *host, char **canonicalname); void sk_addr_free(SockAddr addr); -Socket sk_new(SockAddr addr, int port, int privport, sk_receiver_t receiver); +Socket sk_new(SockAddr addr, int port, int privport, int oobinline, + sk_receiver_t receiver); void sk_close(Socket s); void sk_write(Socket s, char *buf, int len); void sk_write_oob(Socket s, char *buf, int len); diff --git a/raw.c b/raw.c index 9cbb606c..e3d5c06b 100644 --- a/raw.c +++ b/raw.c @@ -66,7 +66,7 @@ static char *raw_init (char *host, int port, char **realhost) { /* * Open socket. */ - s = sk_new(addr, port, 0, raw_receive); + s = sk_new(addr, port, 0, 1, raw_receive); if ( (err = sk_socket_error(s)) ) return err; diff --git a/rlogin.c b/rlogin.c index e20b9e68..8a7b1fa6 100644 --- a/rlogin.c +++ b/rlogin.c @@ -92,7 +92,7 @@ static char *rlogin_init (char *host, int port, char **realhost) { /* * Open socket. */ - s = sk_new(addr, port, 1, rlogin_receive); + s = sk_new(addr, port, 1, 0, rlogin_receive); if ( (err = sk_socket_error(s)) ) return err; diff --git a/ssh.c b/ssh.c index 5ad1ea4a..5a7dcf24 100644 --- a/ssh.c +++ b/ssh.c @@ -1219,7 +1219,7 @@ static char *connect_to_host(char *host, int port, char **realhost) /* * Open socket. */ - s = sk_new(addr, port, 0, ssh_receive); + s = sk_new(addr, port, 0, 1, ssh_receive); if ( (err = sk_socket_error(s)) ) return err; diff --git a/telnet.c b/telnet.c index e9db2104..bf42ed24 100644 --- a/telnet.c +++ b/telnet.c @@ -507,7 +507,7 @@ static char *telnet_init (char *host, int port, char **realhost) { /* * Open socket. */ - s = sk_new(addr, port, 0, telnet_receive); + s = sk_new(addr, port, 0, 1, telnet_receive); if ( (err = sk_socket_error(s)) ) return err; diff --git a/winnet.c b/winnet.c index cc0b080c..f15b136f 100644 --- a/winnet.c +++ b/winnet.c @@ -63,6 +63,7 @@ struct Socket_tag { struct buffer *head, *tail; int writable; int sending_oob; + int oobinline; }; struct SockAddr_tag { @@ -288,7 +289,8 @@ void sk_addr_free(SockAddr addr) { sfree(addr); } -Socket sk_new(SockAddr addr, int port, int privport, sk_receiver_t receiver) { +Socket sk_new(SockAddr addr, int port, int privport, int oobinline, + sk_receiver_t receiver) { SOCKET s; #ifdef IPV6 SOCKADDR_IN6 a6; @@ -321,7 +323,9 @@ Socket sk_new(SockAddr addr, int port, int privport, sk_receiver_t receiver) { ret->error = winsock_error_string(err); return ret; } - { + + ret->oobinline = oobinline; + if (oobinline) { BOOL b = TRUE; setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b)); } @@ -583,13 +587,27 @@ int select_result(WPARAM wParam, LPARAM lParam) { switch (WSAGETSELECTEVENT(lParam)) { case FD_READ: - atmark = 1; - /* Some WinSock wrappers don't support this call, so we - * deliberately don't check the return value. If the call - * fails and does nothing, we will get back atmark==1, - * which is good enough to keep going at least. */ - ioctlsocket(s->s, SIOCATMARK, &atmark); + /* + * We have received data on the socket. For an oobinline + * socket, this might be data _before_ an urgent pointer, + * in which case we send it to the back end with type==1 + * (data prior to urgent). + */ + if (s->oobinline) { + atmark = 1; + ioctlsocket(s->s, SIOCATMARK, &atmark); + /* + * Avoid checking the return value from ioctlsocket(), + * on the grounds that some WinSock wrappers don't + * support it. If it does nothing, we get atmark==1, + * which is equivalent to `no OOB pending', so the + * effect will be to non-OOB-ify any OOB data. + */ + } else + atmark = 1; + ret = recv(s->s, buf, sizeof(buf), 0); + noise_ultralight(ret); if (ret < 0) { err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { @@ -599,19 +617,16 @@ int select_result(WPARAM wParam, LPARAM lParam) { if (ret < 0) { return s->receiver(s, 3, winsock_error_string(err), err); } else { - int type = 0; - if (atmark==0) { - ioctlsocket(s->s, SIOCATMARK, &atmark); - if(atmark) type = 2; else type = 1; - } - return s->receiver(s, type, buf, ret); + return s->receiver(s, atmark ? 0 : 1, buf, ret); } break; case FD_OOB: - /* - * Read all data up to the OOB marker, and send it to the - * receiver with urgent==1 (OOB pending). - */ + /* + * This will only happen on a non-oobinline socket. It + * indicates that we can immediately perform an OOB read + * and get back OOB data, which we will send to the back + * end with type==2 (urgent data). + */ ret = recv(s->s, buf, sizeof(buf), MSG_OOB); noise_ultralight(ret); if (ret <= 0) { diff --git a/x11fwd.c b/x11fwd.c index 7e995239..d0a1f997 100644 --- a/x11fwd.c +++ b/x11fwd.c @@ -163,7 +163,7 @@ char *x11_init (Socket *s, char *display, void *c) { /* * Open socket. */ - *s = sk_new(addr, port, 0, x11_receive); + *s = sk_new(addr, port, 0, 1, x11_receive); if ( (err = sk_socket_error(*s)) ) return err; -- 2.11.0