X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/c9446101efb72d2326890e397ce82b495276e600..1e00c92b81273392a7db4796dc163b0729891e44:/mac/otnet.c diff --git a/mac/otnet.c b/mac/otnet.c index 1033961d..d5271e70 100644 --- a/mac/otnet.c +++ b/mac/otnet.c @@ -6,6 +6,7 @@ #define OTCARBONAPPLICATION 1 #endif +#include /* Needed by OpenTransportInternet.h */ #include #include @@ -36,6 +37,8 @@ struct Socket_tag { int oobinline; int pending_error; /* in case send() returns error */ int listener; + int nodelay, keepalive; + int privport, port; struct Socket_tag *next; struct Socket_tag **prev; }; @@ -80,7 +83,7 @@ void ot_cleanup(void) SockAddr ot_namelookup(char const *host, char **canonicalname) { - SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + SockAddr ret = snew(struct SockAddr_tag); char *realhost; /* Casting away const -- hope OTInetStringToAddress is sensible */ @@ -92,14 +95,14 @@ SockAddr ot_namelookup(char const *host, char **canonicalname) realhost = ret->hostinfo.name; else realhost = ""; - *canonicalname = smalloc(1+strlen(realhost)); + *canonicalname = snewn(1+strlen(realhost), char); strcpy(*canonicalname, realhost); return ret; } SockAddr ot_nonamelookup(char const *host) { - SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + SockAddr ret = snew(struct SockAddr_tag); ret->resolved = FALSE; ret->error = kOTNoError; @@ -184,10 +187,13 @@ static int ot_tcp_write_oob(Socket s, char const *data, int len); static void ot_tcp_set_private_ptr(Socket s, void *ptr); static void *ot_tcp_get_private_ptr(Socket s); static void ot_tcp_set_frozen(Socket s, int is_frozen); -static char *ot_tcp_socket_error(Socket s); +static const char *ot_tcp_socket_error(Socket s); static void ot_recv(Actual_Socket s); +static void ot_listenaccept(Actual_Socket s); +static void ot_setoption(EndpointRef, OTXTILevel, OTXTIName, UInt32); void ot_poll(void); + Socket ot_register(void *sock, Plug plug) { static struct socket_function_table fn_table = { @@ -204,7 +210,7 @@ Socket ot_register(void *sock, Plug plug) Actual_Socket ret; - ret = smalloc(sizeof(struct Socket_tag)); + ret = snew(struct Socket_tag); ret->fn = &fn_table; ret->error = kOTNoError; ret->plug = plug; @@ -233,7 +239,7 @@ Socket ot_register(void *sock, Plug plug) } Socket ot_new(SockAddr addr, int port, int privport, int oobinline, - int nodelay, Plug plug) + int nodelay, int keepalive, Plug plug) { static struct socket_function_table fn_table = { ot_tcp_plug, @@ -253,7 +259,7 @@ Socket ot_new(SockAddr addr, int port, int privport, int oobinline, InetAddress dest; TCall connectCall; - ret = smalloc(sizeof(struct Socket_tag)); + ret = snew(struct Socket_tag); ret->fn = &fn_table; ret->error = kOTNoError; ret->plug = plug; @@ -266,6 +272,8 @@ Socket ot_new(SockAddr addr, int port, int privport, int oobinline, ret->localhost_only = 0; /* unused, but best init anyway */ ret->pending_error = 0; ret->oobinline = oobinline; + ret->nodelay = nodelay; + ret->keepalive = keepalive; ret->oobpending = FALSE; ret->listener = 0; @@ -280,7 +288,15 @@ Socket ot_new(SockAddr addr, int port, int privport, int oobinline, return (Socket) ret; } - /* TODO: oobinline, nodelay */ + if (ret->oobinline) + ot_setoption(ep, INET_TCP, TCP_OOBINLINE, T_YES); + + if (ret->nodelay) + ot_setoption(ep, INET_TCP, TCP_NODELAY, T_YES); + + if (ret->keepalive) { + ot_setoption(ep, INET_TCP, TCP_KEEPALIVE, T_YES); + } /* * Bind to local address. @@ -323,14 +339,84 @@ Socket ot_new(SockAddr addr, int port, int privport, int oobinline, ret->next->prev = &ret->next; ot.socklist = ret; + /* XXX: don't know whether we can sk_addr_free(addr); */ + return (Socket) ret; } -Socket ot_newlistener(char *foobar, int port, Plug plug, int local_host_only) +Socket ot_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, + int address_family) { - Actual_Socket s; + static struct socket_function_table fn_table = { + ot_tcp_plug, + ot_tcp_close, + ot_tcp_write, + ot_tcp_write_oob, + ot_tcp_flush, + ot_tcp_set_private_ptr, + ot_tcp_get_private_ptr, + ot_tcp_set_frozen, + ot_tcp_socket_error + }; + + Actual_Socket ret; + EndpointRef ep; + OSStatus err; + InetAddress addr; + TBind tbind; + + ret = snew(struct Socket_tag); + ret->fn = &fn_table; + ret->error = kOTNoError; + ret->plug = plug; + bufchain_init(&ret->output_data); + ret->writable = 0; /* to start with */ + ret->sending_oob = 0; + ret->frozen = 0; + ret->frozen_readable = 0; + ret->localhost_only = local_host_only; + ret->pending_error = 0; + ret->oobinline = 0; + ret->oobpending = FALSE; + ret->listener = 1; + + /* Open Endpoint, configure it for TCP over anything, and load the + * tilisten module to serialize multiple simultaneous + * connections. */ + + ep = OTOpenEndpoint(OTCreateConfiguration("tilisten,tcp"), 0, NULL, &err); + + ret->ep = ep; + + if (err) { + ret->error = err; + return (Socket) ret; + } + + ot_setoption(ep, INET_IP, IP_REUSEADDR, T_YES); + + OTInitInetAddress(&addr, port, kOTAnyInetAddress); + /* XXX: pay attention to local_host_only */ + + tbind.addr.buf = (UInt8 *) &addr; + tbind.addr.len = sizeof(addr); + tbind.qlen = 10; + + err = OTBind(ep, &tbind, NULL); /* XXX: check qlen we got */ + + if (err) { + ret->error = err; + return (Socket) ret; + } + + /* Add this to the list of all sockets */ + ret->next = ot.socklist; + ret->prev = &ot.socklist; + if (ret->next != NULL) + ret->next->prev = &ret->next; + ot.socklist = ret; - return (Socket) s; + return (Socket) ret; } static void ot_tcp_close(Socket sock) @@ -419,7 +505,7 @@ char *ot_addr_error(SockAddr addr) sprintf(buf, "error %d", addr->error); return buf; } -static char *ot_tcp_socket_error(Socket sock) +static const char *ot_tcp_socket_error(Socket sock) { Actual_Socket s = (Actual_Socket) sock; static char buf[128]; @@ -458,6 +544,15 @@ void ot_poll(void) case T_EXDATA: /* Expedited Data (urgent?) */ ot_recv(s); break; + case T_LISTEN: /* Connection attempt */ + ot_listenaccept(s); + break; + case T_ORDREL: /* Orderly disconnect */ + plug_closing(s->plug, NULL, 0, 0); + break; + case T_DISCONNECT: /* Abortive disconnect*/ + plug_closing(s->plug, NULL, 0, 0); + break; } } } @@ -465,20 +560,76 @@ void ot_poll(void) void ot_recv(Actual_Socket s) { OTResult o; - char buf[20480]; + char buf[2048]; OTFlags flags; if (s->frozen) return; - do { - o = OTRcv(s->ep, buf, sizeof(buf), &flags); - if (o > 0) - plug_receive(s->plug, 0, buf, o); - if (o < 0 && o != kOTNoDataErr) - plug_closing(s->plug, NULL, 0, 0); /* XXX Error msg */ - } while (o > 0); + o = OTRcv(s->ep, buf, sizeof(buf), &flags); + if (o > 0) + plug_receive(s->plug, 0, buf, o); + if (o < 0 && o != kOTNoDataErr) + plug_closing(s->plug, NULL, 0, 0); /* XXX Error msg */ +} + +void ot_listenaccept(Actual_Socket s) +{ + OTResult o; + OSStatus err; + InetAddress remoteaddr; + TCall tcall; + EndpointRef ep; + + tcall.addr.maxlen = sizeof(InetAddress); + tcall.addr.buf = (unsigned char *)&remoteaddr; + tcall.opt.maxlen = 0; + tcall.opt.buf = NULL; + tcall.udata.maxlen = 0; + tcall.udata.buf = NULL; + + o = OTListen(s->ep, &tcall); + + if (o != kOTNoError) + return; + + /* We've found an incoming connection, accept it */ + + ep = OTOpenEndpoint(OTCreateConfiguration("tcp"), 0, NULL, &err); + o = OTAccept(s->ep, ep, &tcall); + if (plug_accepting(s->plug, ep)) { + OTUnbind(ep); + OTCloseProvider(ep); + } } +static void ot_setoption(EndpointRef ep, + OTXTILevel level, + OTXTIName name, + UInt32 value) +{ + TOption option; + TOptMgmt request; + TOptMgmt result; + + if (name == TCP_KEEPALIVE) { + option.len = sizeof(struct t_kpalive); + option.value[1] = T_UNSPEC; + } else + option.len = kOTFourByteOptionSize; + option.level = level; + option.name = name; + option.status = 0; + option.value[0] = value; + + request.opt.buf = (unsigned char *) &option; + request.opt.len = sizeof(option); + request.flags = T_NEGOTIATE; + + result.opt.buf = (unsigned char *) &option; + result.opt.maxlen = sizeof(option); + + OTOptionManagement(ep, &request, &result); +} /* * Local Variables: