From 19fba3fe550785b2584264a59d3dccea81077451 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 17 Nov 2013 14:03:55 +0000 Subject: [PATCH] Replace the hacky 'OSSocket' type with a closure. The mechanism for constructing a new connection-type Socket when a listening one receives an incoming connection previously worked by passing a platform-specific 'OSSocket' type to the plug_accepting function, which would then call sk_register to wrap it with a proper Socket instance. This is less flexible than ideal, because it presumes that only one kind of OS object might ever need to be turned into a Socket. So I've replaced OSSocket throughout the code base with a pair of parameters consisting of a function pointer and a context such that passing the latter to the former returns the appropriate Socket; this will permit different classes of listening Socket to pass different function pointers. In deference to the reality that OSSockets tend to be small integers or pointer-sized OS handles, I've made the context parameter an int/pointer union that can hold either of those directly, rather than the usual approach of making it a plain 'void *' and requiring a context structure to be dynamically allocated every time. [originally from svn r10068] --- network.h | 18 +++++++++--------- portfwd.c | 4 ++-- proxy.c | 20 +++++++++++++------- proxy.h | 3 ++- unix/unix.h | 3 --- unix/uxnet.c | 7 +++++-- windows/winnet.c | 10 +++++++--- x11fwd.c | 2 +- 8 files changed, 39 insertions(+), 28 deletions(-) diff --git a/network.h b/network.h index 5192529b..d35ff00c 100644 --- a/network.h +++ b/network.h @@ -25,10 +25,6 @@ typedef struct SockAddr_tag *SockAddr; typedef struct socket_function_table **Socket; typedef struct plug_function_table **Plug; -#ifndef OSSOCKET_DEFINED -typedef void *OSSocket; -#endif - struct socket_function_table { Plug(*plug) (Socket s, Plug p); /* use a different plug (return the old one) */ @@ -46,6 +42,9 @@ struct socket_function_table { const char *(*socket_error) (Socket s); }; +typedef union { void *p; int i; } accept_ctx_t; +typedef Socket (*accept_fn_t)(accept_ctx_t ctx, Plug plug); + struct plug_function_table { void (*log)(Plug p, int type, SockAddr addr, int port, const char *error_msg, int error_code); @@ -83,9 +82,12 @@ struct plug_function_table { * on a socket is cleared or partially cleared. The new backlog * size is passed in the `bufsize' parameter. */ - int (*accepting)(Plug p, OSSocket sock); + int (*accepting)(Plug p, accept_fn_t constructor, accept_ctx_t ctx); /* - * returns 0 if the host at address addr is a valid host for connecting or error + * `accepting' is called only on listener-type sockets, and is + * passed a constructor function+context that will create a fresh + * Socket describing the connection. It returns nonzero if it + * doesn't want the connection for some reason, or 0 on success. */ }; @@ -136,8 +138,6 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family); -Socket sk_register(OSSocket sock, Plug plug); - #define sk_plug(s,p) (((*s)->plug) (s, p)) #define sk_close(s) (((*s)->close) (s)) #define sk_write(s,buf,len) (((*s)->write) (s, buf, len)) @@ -150,7 +150,7 @@ Socket sk_register(OSSocket sock, Plug plug); #define plug_closing(p,msg,code,callback) (((*p)->closing) (p, msg, code, callback)) #define plug_receive(p,urgent,buf,len) (((*p)->receive) (p, urgent, buf, len)) #define plug_sent(p,bufsize) (((*p)->sent) (p, bufsize)) -#define plug_accepting(p, sock) (((*p)->accepting)(p, sock)) +#define plug_accepting(p, constructor, ctx) (((*p)->accepting)(p, constructor, ctx)) #endif /* diff --git a/portfwd.c b/portfwd.c index a93bb066..b14458b9 100644 --- a/portfwd.c +++ b/portfwd.c @@ -411,7 +411,7 @@ const char *pfd_newconnect(Socket *s, char *hostname, int port, called when someone connects to the local port */ -static int pfd_accepting(Plug p, OSSocket sock) +static int pfd_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx) { static const struct plug_function_table fn_table = { pfd_log, @@ -431,7 +431,7 @@ static int pfd_accepting(Plug p, OSSocket sock) pr->c = NULL; pr->backhandle = org->backhandle; - pr->s = s = sk_register(sock, (Plug) pr); + pr->s = s = constructor(ctx, (Plug) pr); if ((err = sk_socket_error(s)) != NULL) { free_portfwd_private(pr); return err != NULL; diff --git a/proxy.c b/proxy.c index 8a146231..01eaa34a 100644 --- a/proxy.c +++ b/proxy.c @@ -261,16 +261,18 @@ static void plug_proxy_sent (Plug p, int bufsize) plug_sent(ps->plug, bufsize); } -static int plug_proxy_accepting (Plug p, OSSocket sock) +static int plug_proxy_accepting(Plug p, + accept_fn_t constructor, accept_ctx_t ctx) { Proxy_Plug pp = (Proxy_Plug) p; Proxy_Socket ps = pp->proxy_socket; if (ps->state != PROXY_STATE_ACTIVE) { - ps->accepting_sock = sock; + ps->accepting_constructor = constructor; + ps->accepting_ctx = ctx; return ps->negotiate(ps, PROXY_CHANGE_ACCEPTING); } - return plug_accepting(ps->plug, sock); + return plug_accepting(ps->plug, constructor, ctx); } /* @@ -617,7 +619,8 @@ int proxy_http_negotiate (Proxy_Socket p, int change) * what should we do? close the socket with an appropriate * error message? */ - return plug_accepting(p->plug, p->accepting_sock); + return plug_accepting(p->plug, + p->accepting_constructor, p->accepting_ctx); } if (change == PROXY_CHANGE_RECEIVE) { @@ -819,7 +822,8 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change) * what should we do? close the socket with an appropriate * error message? */ - return plug_accepting(p->plug, p->accepting_sock); + return plug_accepting(p->plug, + p->accepting_constructor, p->accepting_ctx); } if (change == PROXY_CHANGE_RECEIVE) { @@ -958,7 +962,8 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change) * what should we do? close the socket with an appropriate * error message? */ - return plug_accepting(p->plug, p->accepting_sock); + return plug_accepting(p->plug, + p->accepting_constructor, p->accepting_ctx); } if (change == PROXY_CHANGE_RECEIVE) { @@ -1496,7 +1501,8 @@ int proxy_telnet_negotiate (Proxy_Socket p, int change) * what should we do? close the socket with an appropriate * error message? */ - return plug_accepting(p->plug, p->accepting_sock); + return plug_accepting(p->plug, + p->accepting_constructor, p->accepting_ctx); } if (change == PROXY_CHANGE_RECEIVE) { diff --git a/proxy.h b/proxy.h index 10a8c677..12b47e16 100644 --- a/proxy.h +++ b/proxy.h @@ -78,7 +78,8 @@ struct Socket_proxy_tag { int sent_bufsize; /* accepting */ - OSSocket accepting_sock; + accept_fn_t accepting_constructor; + accept_ctx_t accepting_ctx; /* configuration, used to look up proxy settings */ Conf *conf; diff --git a/unix/unix.h b/unix/unix.h index c2f9aeb1..d43e0ae0 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -24,9 +24,6 @@ struct FontSpec *fontspec_new(const char *name); typedef void *Context; /* FIXME: probably needs changing */ -typedef int OSSocket; -#define OSSOCKET_DEFINED /* stop network.h using its default */ - extern Backend pty_backend; typedef uint32_t uint32; /* C99: uint32_t defined in stdint.h */ diff --git a/unix/uxnet.c b/unix/uxnet.c index 9fc649f7..f15795cf 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -490,8 +490,9 @@ static struct socket_function_table tcp_fn_table = { sk_tcp_socket_error }; -Socket sk_register(OSSocket sockfd, Plug plug) +static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug) { + int sockfd = ctx.i; Actual_Socket ret; /* @@ -1268,6 +1269,7 @@ static int net_select_result(int fd, int event) */ union sockaddr_union su; socklen_t addrlen = sizeof(su); + accept_ctx_t actx; int t; /* socket of connection */ memset(&su, 0, addrlen); @@ -1277,11 +1279,12 @@ static int net_select_result(int fd, int event) } nonblock(t); + actx.i = t; if (s->localhost_only && !sockaddr_is_loopback(&su.sa)) { close(t); /* someone let nonlocal through?! */ - } else if (plug_accepting(s->plug, t)) { + } else if (plug_accepting(s->plug, sk_tcp_accept, actx)) { close(t); /* denied or error */ } break; diff --git a/windows/winnet.c b/windows/winnet.c index 4069c5d8..b6c9fa61 100644 --- a/windows/winnet.c +++ b/windows/winnet.c @@ -835,7 +835,7 @@ static const char *sk_tcp_socket_error(Socket s); extern char *do_select(SOCKET skt, int startup); -Socket sk_register(void *sock, Plug plug) +static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug) { static const struct socket_function_table fn_table = { sk_tcp_plug, @@ -872,7 +872,7 @@ Socket sk_register(void *sock, Plug plug) ret->parent = ret->child = NULL; ret->addr = NULL; - ret->s = (SOCKET)sock; + ret->s = (SOCKET)ctx.p; if (ret->s == INVALID_SOCKET) { err = p_WSAGetLastError(); @@ -1660,6 +1660,7 @@ int select_result(WPARAM wParam, LPARAM lParam) #endif int addrlen = sizeof(isa); SOCKET t; /* socket of connection */ + accept_ctx_t actx; memset(&isa, 0, sizeof(isa)); err = 0; @@ -1670,6 +1671,9 @@ int select_result(WPARAM wParam, LPARAM lParam) if (err == WSATRY_AGAIN) break; } + + actx.p = (void *)t; + #ifndef NO_IPV6 if (isa.ss_family == AF_INET && s->localhost_only && @@ -1679,7 +1683,7 @@ int select_result(WPARAM wParam, LPARAM lParam) #endif { p_closesocket(t); /* dodgy WinSock let nonlocal through */ - } else if (plug_accepting(s->plug, (void*)t)) { + } else if (plug_accepting(s->plug, sk_tcp_accept, actx)) { p_closesocket(t); /* denied or error */ } } diff --git a/x11fwd.c b/x11fwd.c index d848b218..ba729d18 100644 --- a/x11fwd.c +++ b/x11fwd.c @@ -62,7 +62,7 @@ static int dummy_plug_closing static int dummy_plug_receive(Plug p, int urgent, char *data, int len) { return 1; } static void dummy_plug_sent(Plug p, int bufsize) { } -static int dummy_plug_accepting(Plug p, OSSocket sock) { return 1; } +static int dummy_plug_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx) { return 1; } static const struct plug_function_table dummy_plug = { dummy_plug_log, dummy_plug_closing, dummy_plug_receive, dummy_plug_sent, dummy_plug_accepting -- 2.45.2