1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 11:32:48 -05:00

Modernise the Socket/Plug vtable system.

Now I've got FROMFIELD, I can rework it so that structures providing
an implementation of the Socket or Plug trait no longer have to have
the vtable pointer as the very first thing in the structure. In
particular, this means that the ProxySocket structure can now directly
implement _both_ the Socket and Plug traits, which is always
_logically_ how it's worked, but previously it had to be implemented
via two separate structs linked to each other.
This commit is contained in:
Simon Tatham
2018-05-27 09:29:33 +01:00
parent 0fc2d3b455
commit 5129c40bea
24 changed files with 675 additions and 734 deletions

View File

@ -12,12 +12,7 @@
#include "putty.h"
#include "network.h"
typedef struct Socket_handle_tag *Handle_Socket;
struct Socket_handle_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct HandleSocket {
HANDLE send_H, recv_H, stderr_H;
struct handle *send_h, *recv_h, *stderr_h;
@ -47,29 +42,31 @@ struct Socket_handle_tag {
char *error;
Plug plug;
};
const Socket_vtable *sockvt;
} HandleSocket;
static int handle_gotdata(struct handle *h, void *data, int len)
{
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
if (len < 0) {
plug_closing(ps->plug, "Read error from handle", 0, 0);
plug_closing(hs->plug, "Read error from handle", 0, 0);
return 0;
} else if (len == 0) {
plug_closing(ps->plug, NULL, 0, 0);
plug_closing(hs->plug, NULL, 0, 0);
return 0;
} else {
assert(ps->frozen != FROZEN && ps->frozen != THAWING);
if (ps->frozen == FREEZING) {
assert(hs->frozen != FROZEN && hs->frozen != THAWING);
if (hs->frozen == FREEZING) {
/*
* If we've received data while this socket is supposed to
* be frozen (because the read winhandl.c started before
* sk_set_frozen was called has now returned) then buffer
* the data for when we unfreeze.
*/
bufchain_add(&ps->inputdata, data, len);
ps->frozen = FROZEN;
bufchain_add(&hs->inputdata, data, len);
hs->frozen = FROZEN;
/*
* And return a very large backlog, to prevent further
@ -77,7 +74,7 @@ static int handle_gotdata(struct handle *h, void *data, int len)
*/
return INT_MAX;
} else {
plug_receive(ps->plug, 0, data, len);
plug_receive(hs->plug, 0, data, len);
return 0;
}
}
@ -85,63 +82,63 @@ static int handle_gotdata(struct handle *h, void *data, int len)
static int handle_stderr(struct handle *h, void *data, int len)
{
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
if (len > 0)
log_proxy_stderr(ps->plug, &ps->stderrdata, data, len);
log_proxy_stderr(hs->plug, &hs->stderrdata, data, len);
return 0;
}
static void handle_sentdata(struct handle *h, int new_backlog)
{
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
if (new_backlog < 0) {
/* Special case: this is actually reporting an error writing
* to the underlying handle, and our input value is the error
* code itself, negated. */
plug_closing(ps->plug, win_strerror(-new_backlog), -new_backlog, 0);
plug_closing(hs->plug, win_strerror(-new_backlog), -new_backlog, 0);
return;
}
plug_sent(ps->plug, new_backlog);
plug_sent(hs->plug, new_backlog);
}
static Plug sk_handle_plug(Socket s, Plug p)
{
Handle_Socket ps = (Handle_Socket) s;
Plug ret = ps->plug;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
Plug ret = hs->plug;
if (p)
ps->plug = p;
hs->plug = p;
return ret;
}
static void sk_handle_close(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
if (ps->defer_close) {
ps->deferred_close = TRUE;
if (hs->defer_close) {
hs->deferred_close = TRUE;
return;
}
handle_free(ps->send_h);
handle_free(ps->recv_h);
CloseHandle(ps->send_H);
if (ps->recv_H != ps->send_H)
CloseHandle(ps->recv_H);
bufchain_clear(&ps->inputdata);
bufchain_clear(&ps->stderrdata);
handle_free(hs->send_h);
handle_free(hs->recv_h);
CloseHandle(hs->send_H);
if (hs->recv_H != hs->send_H)
CloseHandle(hs->recv_H);
bufchain_clear(&hs->inputdata);
bufchain_clear(&hs->stderrdata);
sfree(ps);
sfree(hs);
}
static int sk_handle_write(Socket s, const void *data, int len)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
return handle_write(ps->send_h, data, len);
return handle_write(hs->send_h, data, len);
}
static int sk_handle_write_oob(Socket s, const void *data, int len)
@ -155,20 +152,20 @@ static int sk_handle_write_oob(Socket s, const void *data, int len)
static void sk_handle_write_eof(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
handle_write_eof(ps->send_h);
handle_write_eof(hs->send_h);
}
static void sk_handle_flush(Socket s)
{
/* Handle_Socket ps = (Handle_Socket) s; */
/* HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt); */
/* do nothing */
}
static void handle_socket_unfreeze(void *psv)
static void handle_socket_unfreeze(void *hsv)
{
Handle_Socket ps = (Handle_Socket) psv;
HandleSocket *hs = (HandleSocket *)hsv;
void *data;
int len;
@ -176,49 +173,49 @@ static void handle_socket_unfreeze(void *psv)
* If we've been put into a state other than THAWING since the
* last callback, then we're done.
*/
if (ps->frozen != THAWING)
if (hs->frozen != THAWING)
return;
/*
* Get some of the data we've buffered.
*/
bufchain_prefix(&ps->inputdata, &data, &len);
bufchain_prefix(&hs->inputdata, &data, &len);
assert(len > 0);
/*
* Hand it off to the plug. Be careful of re-entrance - that might
* have the effect of trying to close this socket.
*/
ps->defer_close = TRUE;
plug_receive(ps->plug, 0, data, len);
bufchain_consume(&ps->inputdata, len);
ps->defer_close = FALSE;
if (ps->deferred_close) {
sk_handle_close((Socket)ps);
hs->defer_close = TRUE;
plug_receive(hs->plug, 0, data, len);
bufchain_consume(&hs->inputdata, len);
hs->defer_close = FALSE;
if (hs->deferred_close) {
sk_handle_close(&hs->sockvt);
return;
}
if (bufchain_size(&ps->inputdata) > 0) {
if (bufchain_size(&hs->inputdata) > 0) {
/*
* If there's still data in our buffer, stay in THAWING state,
* and reschedule ourself.
*/
queue_toplevel_callback(handle_socket_unfreeze, ps);
queue_toplevel_callback(handle_socket_unfreeze, hs);
} else {
/*
* Otherwise, we've successfully thawed!
*/
ps->frozen = UNFROZEN;
handle_unthrottle(ps->recv_h, 0);
hs->frozen = UNFROZEN;
handle_unthrottle(hs->recv_h, 0);
}
}
static void sk_handle_set_frozen(Socket s, int is_frozen)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
if (is_frozen) {
switch (ps->frozen) {
switch (hs->frozen) {
case FREEZING:
case FROZEN:
return; /* nothing to do */
@ -230,7 +227,7 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* throttled, so just return to FROZEN state. The toplevel
* callback will notice and disable itself.
*/
ps->frozen = FROZEN;
hs->frozen = FROZEN;
break;
case UNFROZEN:
@ -238,11 +235,11 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* The normal case. Go to FREEZING, and expect one more
* load of data from winhandl if we're unlucky.
*/
ps->frozen = FREEZING;
hs->frozen = FREEZING;
break;
}
} else {
switch (ps->frozen) {
switch (hs->frozen) {
case UNFROZEN:
case THAWING:
return; /* nothing to do */
@ -253,8 +250,8 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* we were frozen, then we'll still be in this state and
* can just unfreeze in the trivial way.
*/
assert(bufchain_size(&ps->inputdata) == 0);
ps->frozen = UNFROZEN;
assert(bufchain_size(&hs->inputdata) == 0);
hs->frozen = UNFROZEN;
break;
case FROZEN:
@ -262,21 +259,21 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* If we have buffered data, go to THAWING and start
* releasing it in top-level callbacks.
*/
ps->frozen = THAWING;
queue_toplevel_callback(handle_socket_unfreeze, ps);
hs->frozen = THAWING;
queue_toplevel_callback(handle_socket_unfreeze, hs);
}
}
}
static const char *sk_handle_socket_error(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
return ps->error;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
return hs->error;
}
static char *sk_handle_peer_info(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
ULONG pid;
static HMODULE kernel32_module;
DECL_WINDOWS_FUNCTION(static, BOOL, GetNamedPipeClientProcessId,
@ -303,48 +300,48 @@ static char *sk_handle_peer_info(Socket s)
* to log what we can find out about the client end.
*/
if (p_GetNamedPipeClientProcessId &&
p_GetNamedPipeClientProcessId(ps->send_H, &pid))
p_GetNamedPipeClientProcessId(hs->send_H, &pid))
return dupprintf("process id %lu", (unsigned long)pid);
return NULL;
}
static const Socket_vtable HandleSocket_sockvt = {
sk_handle_plug,
sk_handle_close,
sk_handle_write,
sk_handle_write_oob,
sk_handle_write_eof,
sk_handle_flush,
sk_handle_set_frozen,
sk_handle_socket_error,
sk_handle_peer_info,
};
Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
Plug plug, int overlapped)
{
static const struct socket_function_table socket_fn_table = {
sk_handle_plug,
sk_handle_close,
sk_handle_write,
sk_handle_write_oob,
sk_handle_write_eof,
sk_handle_flush,
sk_handle_set_frozen,
sk_handle_socket_error,
sk_handle_peer_info,
};
Handle_Socket ret;
HandleSocket *hs;
int flags = (overlapped ? HANDLE_FLAG_OVERLAPPED : 0);
ret = snew(struct Socket_handle_tag);
ret->fn = &socket_fn_table;
ret->plug = plug;
ret->error = NULL;
ret->frozen = UNFROZEN;
bufchain_init(&ret->inputdata);
bufchain_init(&ret->stderrdata);
hs = snew(HandleSocket);
hs->sockvt = &HandleSocket_sockvt;
hs->plug = plug;
hs->error = NULL;
hs->frozen = UNFROZEN;
bufchain_init(&hs->inputdata);
bufchain_init(&hs->stderrdata);
ret->recv_H = recv_H;
ret->recv_h = handle_input_new(ret->recv_H, handle_gotdata, ret, flags);
ret->send_H = send_H;
ret->send_h = handle_output_new(ret->send_H, handle_sentdata, ret, flags);
ret->stderr_H = stderr_H;
if (ret->stderr_H)
ret->stderr_h = handle_input_new(ret->stderr_H, handle_stderr,
ret, flags);
hs->recv_H = recv_H;
hs->recv_h = handle_input_new(hs->recv_H, handle_gotdata, hs, flags);
hs->send_H = send_H;
hs->send_h = handle_output_new(hs->send_H, handle_sentdata, hs, flags);
hs->stderr_H = stderr_H;
if (hs->stderr_H)
hs->stderr_h = handle_input_new(hs->stderr_H, handle_stderr,
hs, flags);
ret->defer_close = ret->deferred_close = FALSE;
hs->defer_close = hs->deferred_close = FALSE;
return (Socket) ret;
return &hs->sockvt;
}

View File

@ -35,16 +35,6 @@ const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
#define ipv4_is_loopback(addr) \
((p_ntohl(addr.s_addr) & 0xFF000000L) == 0x7F000000L)
/*
* We used to typedef struct Socket_tag *Socket.
*
* Since we have made the networking abstraction slightly more
* abstract, Socket no longer means a tcp socket (it could mean
* an ssl socket). So now we must use Actual_Socket when we know
* we are talking about a tcp socket.
*/
typedef struct Socket_tag *Actual_Socket;
/*
* Mutable state that goes with a SockAddr: stores information
* about where in the list of candidate IP(v*) addresses we've
@ -58,9 +48,8 @@ struct SockAddrStep_tag {
int curraddr;
};
struct Socket_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct NetSocket NetSocket;
struct NetSocket {
const char *error;
SOCKET s;
Plug plug;
@ -85,7 +74,9 @@ struct Socket_tag {
* example. So here we define `parent' and `child' pointers to
* track this link.
*/
Actual_Socket parent, child;
NetSocket *parent, *child;
const Socket_vtable *sockvt;
};
struct SockAddr_tag {
@ -133,7 +124,7 @@ static tree234 *sktree;
static int cmpfortree(void *av, void *bv)
{
Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
NetSocket *a = (NetSocket *)av, *b = (NetSocket *)bv;
unsigned long as = (unsigned long) a->s, bs = (unsigned long) b->s;
if (as < bs)
return -1;
@ -148,7 +139,7 @@ static int cmpfortree(void *av, void *bv)
static int cmpforsearch(void *av, void *bv)
{
Actual_Socket b = (Actual_Socket) bv;
NetSocket *b = (NetSocket *)bv;
uintptr_t as = (uintptr_t) av, bs = (uintptr_t) b->s;
if (as < bs)
return -1;
@ -310,7 +301,7 @@ void sk_init(void)
GET_WINDOWS_FUNCTION(winsock_module, htonl);
GET_WINDOWS_FUNCTION(winsock_module, htons);
GET_WINDOWS_FUNCTION(winsock_module, ntohs);
GET_WINDOWS_FUNCTION(winsock_module, gethostname);
GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, gethostname);
#else
/* The toolchain I use for Windows Coverity builds doesn't know
* the type signatures of these */
@ -356,7 +347,7 @@ void sk_init(void)
void sk_cleanup(void)
{
Actual_Socket s;
NetSocket *s;
int i;
if (sktree) {
@ -913,16 +904,16 @@ SockAddr sk_addr_dup(SockAddr addr)
return addr;
}
static Plug sk_tcp_plug(Socket sock, Plug p)
static Plug sk_net_plug(Socket sock, Plug p)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
Plug ret = s->plug;
if (p)
s->plug = p;
return ret;
}
static void sk_tcp_flush(Socket s)
static void sk_net_flush(Socket s)
{
/*
* We send data to the socket as soon as we can anyway,
@ -930,39 +921,39 @@ static void sk_tcp_flush(Socket s)
*/
}
static void sk_tcp_close(Socket s);
static int sk_tcp_write(Socket s, const void *data, int len);
static int sk_tcp_write_oob(Socket s, const void *data, int len);
static void sk_tcp_write_eof(Socket s);
static void sk_tcp_set_frozen(Socket s, int is_frozen);
static const char *sk_tcp_socket_error(Socket s);
static char *sk_tcp_peer_info(Socket s);
static void sk_net_close(Socket s);
static int sk_net_write(Socket s, const void *data, int len);
static int sk_net_write_oob(Socket s, const void *data, int len);
static void sk_net_write_eof(Socket s);
static void sk_net_set_frozen(Socket s, int is_frozen);
static const char *sk_net_socket_error(Socket s);
static char *sk_net_peer_info(Socket s);
extern char *do_select(SOCKET skt, int startup);
static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
};
static const Socket_vtable NetSocket_sockvt = {
sk_net_plug,
sk_net_close,
sk_net_write,
sk_net_write_oob,
sk_net_write_eof,
sk_net_flush,
sk_net_set_frozen,
sk_net_socket_error,
sk_net_peer_info,
};
static Socket sk_net_accept(accept_ctx_t ctx, Plug plug)
{
DWORD err;
char *errstr;
Actual_Socket ret;
NetSocket *ret;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -981,7 +972,7 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
if (ret->s == INVALID_SOCKET) {
err = p_WSAGetLastError();
ret->error = winsock_error_string(err);
return (Socket) ret;
return &ret->sockvt;
}
ret->oobinline = 0;
@ -991,15 +982,15 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
errstr = do_select(ret->s, 1);
if (errstr) {
ret->error = errstr;
return (Socket) ret;
return &ret->sockvt;
}
add234(sktree, ret);
return (Socket) ret;
return &ret->sockvt;
}
static DWORD try_connect(Actual_Socket sock)
static DWORD try_connect(NetSocket *sock)
{
SOCKET s;
#ifndef NO_IPV6
@ -1200,26 +1191,14 @@ static DWORD try_connect(Actual_Socket sock)
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, int keepalive, Plug plug)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
};
Actual_Socket ret;
NetSocket *ret;
DWORD err;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -1246,24 +1225,12 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
err = try_connect(ret);
} while (err && sk_nextaddr(ret->addr, &ret->step));
return (Socket) ret;
return &ret->sockvt;
}
Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
int local_host_only, int orig_address_family)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
};
SOCKET s;
#ifndef NO_IPV6
SOCKADDR_IN6 a6;
@ -1272,17 +1239,17 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
DWORD err;
char *errstr;
Actual_Socket ret;
NetSocket *ret;
int retcode;
int on = 1;
int address_family;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -1324,10 +1291,10 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (s == INVALID_SOCKET) {
err = p_WSAGetLastError();
ret->error = winsock_error_string(err);
return (Socket) ret;
return &ret->sockvt;
}
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
ret->oobinline = 0;
@ -1410,14 +1377,14 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (err) {
p_closesocket(s);
ret->error = winsock_error_string(err);
return (Socket) ret;
return &ret->sockvt;
}
if (p_listen(s, SOMAXCONN) == SOCKET_ERROR) {
p_closesocket(s);
ret->error = winsock_error_string(p_WSAGetLastError());
return (Socket) ret;
return &ret->sockvt;
}
/* Set up a select mechanism. This could be an AsyncSelect on a
@ -1426,7 +1393,7 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (errstr) {
p_closesocket(s);
ret->error = errstr;
return (Socket) ret;
return &ret->sockvt;
}
add234(sktree, ret);
@ -1437,32 +1404,31 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
* IPv6 listening socket and link it to this one.
*/
if (address_family == AF_INET && orig_address_family == ADDRTYPE_UNSPEC) {
Actual_Socket other;
other = (Actual_Socket) sk_newlistener(srcaddr, port, plug,
local_host_only, ADDRTYPE_IPV6);
Socket other = sk_newlistener(srcaddr, port, plug,
local_host_only, ADDRTYPE_IPV6);
if (other) {
if (!other->error) {
other->parent = ret;
ret->child = other;
NetSocket *ns = FROMFIELD(other, NetSocket, sockvt);
if (!ns->error) {
ns->parent = ret;
ret->child = ns;
} else {
sfree(other);
sfree(ns);
}
}
}
#endif
return (Socket) ret;
return &ret->sockvt;
}
static void sk_tcp_close(Socket sock)
static void sk_net_close(Socket sock)
{
extern char *do_select(SOCKET skt, int startup);
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
if (s->child)
sk_tcp_close((Socket)s->child);
sk_net_close(&s->child->sockvt);
del234(sktree, s);
do_select(s->s, 0);
@ -1477,7 +1443,7 @@ static void sk_tcp_close(Socket sock)
*/
static void socket_error_callback(void *vs)
{
Actual_Socket s = (Actual_Socket)vs;
NetSocket *s = (NetSocket *)vs;
/*
* Just in case other socket work has caused this socket to vanish
@ -1497,7 +1463,7 @@ static void socket_error_callback(void *vs)
* The function which tries to send on a socket once it's deemed
* writable.
*/
void try_send(Actual_Socket s)
void try_send(NetSocket *s)
{
while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
int nsent;
@ -1568,9 +1534,9 @@ void try_send(Actual_Socket s)
}
}
static int sk_tcp_write(Socket sock, const void *buf, int len)
static int sk_net_write(Socket sock, const void *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1588,9 +1554,9 @@ static int sk_tcp_write(Socket sock, const void *buf, int len)
return bufchain_size(&s->output_data);
}
static int sk_tcp_write_oob(Socket sock, const void *buf, int len)
static int sk_net_write_oob(Socket sock, const void *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1611,9 +1577,9 @@ static int sk_tcp_write_oob(Socket sock, const void *buf, int len)
return s->sending_oob;
}
static void sk_tcp_write_eof(Socket sock)
static void sk_net_write_eof(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1634,7 +1600,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
int ret;
DWORD err;
char buf[20480]; /* nice big buffer for plenty of speed */
Actual_Socket s;
NetSocket *s;
u_long atmark;
/* wParam is the socket itself */
@ -1798,7 +1764,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
#endif
{
p_closesocket(t); /* dodgy WinSock let nonlocal through */
} else if (plug_accepting(s->plug, sk_tcp_accept, actx)) {
} else if (plug_accepting(s->plug, sk_net_accept, actx)) {
p_closesocket(t); /* denied or error */
}
}
@ -1814,15 +1780,15 @@ const char *sk_addr_error(SockAddr addr)
{
return addr->error;
}
static const char *sk_tcp_socket_error(Socket sock)
static const char *sk_net_socket_error(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
return s->error;
}
static char *sk_tcp_peer_info(Socket sock)
static char *sk_net_peer_info(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
#ifdef NO_IPV6
struct sockaddr_in addr;
#else
@ -1852,9 +1818,9 @@ static char *sk_tcp_peer_info(Socket sock)
}
}
static void sk_tcp_set_frozen(Socket sock, int is_frozen)
static void sk_net_set_frozen(Socket sock, int is_frozen)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
if (s->frozen == is_frozen)
return;
s->frozen = is_frozen;
@ -1870,7 +1836,7 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen)
void socket_reselect_all(void)
{
Actual_Socket s;
NetSocket *s;
int i;
for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
@ -1884,7 +1850,7 @@ void socket_reselect_all(void)
*/
SOCKET first_socket(int *state)
{
Actual_Socket s;
NetSocket *s;
*state = 0;
s = index234(sktree, (*state)++);
return s ? s->s : INVALID_SOCKET;
@ -1892,13 +1858,13 @@ SOCKET first_socket(int *state)
SOCKET next_socket(int *state)
{
Actual_Socket s = index234(sktree, (*state)++);
NetSocket *s = index234(sktree, (*state)++);
return s ? s->s : INVALID_SOCKET;
}
extern int socket_writable(SOCKET skt)
{
Actual_Socket s = find234(sktree, (void *)skt, cmpforsearch);
NetSocket *s = find234(sktree, (void *)skt, cmpforsearch);
if (s)
return bufchain_size(&s->output_data) > 0;

View File

@ -19,11 +19,7 @@
Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
Plug plug, int overlapped);
typedef struct Socket_named_pipe_server_tag *Named_Pipe_Server_Socket;
struct Socket_named_pipe_server_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct NamedPipeServerSocket {
/* Parameters for (repeated) creation of named pipe objects */
PSECURITY_DESCRIPTOR psd;
PACL acl;
@ -37,11 +33,13 @@ struct Socket_named_pipe_server_tag {
/* PuTTY Socket machinery */
Plug plug;
char *error;
};
const Socket_vtable *sockvt;
} NamedPipeServerSocket;
static Plug sk_namedpipeserver_plug(Socket s, Plug p)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
NamedPipeServerSocket *ps = FROMFIELD(s, NamedPipeServerSocket, sockvt);
Plug ret = ps->plug;
if (p)
ps->plug = p;
@ -50,7 +48,7 @@ static Plug sk_namedpipeserver_plug(Socket s, Plug p)
static void sk_namedpipeserver_close(Socket s)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
NamedPipeServerSocket *ps = FROMFIELD(s, NamedPipeServerSocket, sockvt);
if (ps->callback_handle)
handle_free(ps->callback_handle);
@ -67,7 +65,7 @@ static void sk_namedpipeserver_close(Socket s)
static const char *sk_namedpipeserver_socket_error(Socket s)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
NamedPipeServerSocket *ps = FROMFIELD(s, NamedPipeServerSocket, sockvt);
return ps->error;
}
@ -76,7 +74,7 @@ static char *sk_namedpipeserver_peer_info(Socket s)
return NULL;
}
static int create_named_pipe(Named_Pipe_Server_Socket ps, int first_instance)
static int create_named_pipe(NamedPipeServerSocket *ps, int first_instance)
{
SECURITY_ATTRIBUTES sa;
@ -129,7 +127,7 @@ static Socket named_pipe_accept(accept_ctx_t ctx, Plug plug)
*/
SockAddr sk_namedpipe_addr(const char *pipename);
static void named_pipe_accept_loop(Named_Pipe_Server_Socket ps,
static void named_pipe_accept_loop(NamedPipeServerSocket *ps,
int got_one_already)
{
while (1) {
@ -198,32 +196,30 @@ static void named_pipe_accept_loop(Named_Pipe_Server_Socket ps,
static void named_pipe_connect_callback(void *vps)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket)vps;
NamedPipeServerSocket *ps = (NamedPipeServerSocket *)vps;
named_pipe_accept_loop(ps, TRUE);
}
/*
* This socket type is only used for listening, so it should never
* be asked to write or flush or set_frozen.
*/
static const Socket_vtable NamedPipeServerSocket_sockvt = {
sk_namedpipeserver_plug,
sk_namedpipeserver_close,
NULL /* write */,
NULL /* write_oob */,
NULL /* write_eof */,
NULL /* flush */,
NULL /* set_frozen */,
sk_namedpipeserver_socket_error,
sk_namedpipeserver_peer_info,
};
Socket new_named_pipe_listener(const char *pipename, Plug plug)
{
/*
* This socket type is only used for listening, so it should never
* be asked to write or flush or set_frozen.
*/
static const struct socket_function_table socket_fn_table = {
sk_namedpipeserver_plug,
sk_namedpipeserver_close,
NULL /* write */,
NULL /* write_oob */,
NULL /* write_eof */,
NULL /* flush */,
NULL /* set_frozen */,
sk_namedpipeserver_socket_error,
sk_namedpipeserver_peer_info,
};
Named_Pipe_Server_Socket ret;
ret = snew(struct Socket_named_pipe_server_tag);
ret->fn = &socket_fn_table;
NamedPipeServerSocket *ret = snew(NamedPipeServerSocket);
ret->sockvt = &NamedPipeServerSocket_sockvt;
ret->plug = plug;
ret->error = NULL;
ret->psd = NULL;
@ -253,7 +249,7 @@ Socket new_named_pipe_listener(const char *pipename, Plug plug)
named_pipe_accept_loop(ret, FALSE);
cleanup:
return (Socket) ret;
return &ret->sockvt;
}
#endif /* !defined NO_SECURITY */