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]
This commit is contained in:
Simon Tatham 2013-11-17 14:03:55 +00:00
Родитель 9093071faa
Коммит 19fba3fe55
8 изменённых файлов: 39 добавлений и 28 удалений

Просмотреть файл

@ -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
/*

Просмотреть файл

@ -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;

20
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) {

Просмотреть файл

@ -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;

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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;

Просмотреть файл

@ -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 */
}
}

Просмотреть файл

@ -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