From: ben Date: Sat, 11 Jan 2003 23:33:57 +0000 (+0000) Subject: Initial import of Owen's OpenTransport interface. It doesn't work yet, but X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/putty/commitdiff_plain/27a3458f34afd8c533f33d980228acd2f7eef856 Initial import of Owen's OpenTransport interface. It doesn't work yet, but it does compile and link. git-svn-id: svn://svn.tartarus.org/sgt/putty@2547 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/Recipe b/Recipe index deb9681f..c838451e 100644 --- a/Recipe +++ b/Recipe @@ -111,7 +111,7 @@ SFTP = sftp int64 logging WINMISC = misc version winstore settings tree234 winnet proxy cmdline + windefs winmisc UXMISC = misc version uxstore settings tree234 uxnet proxy cmdline -MACMISC = misc version macstore settings tree234 macnet mtcpnet proxy +MACMISC = misc version macstore settings tree234 macnet mtcpnet otnet proxy # Character set library, for use in pterm. CHARSET = sbcsdat slookup sbcs utf8 toucs fromucs xenc mimeenc macenc diff --git a/mac/mac.c b/mac/mac.c index 632b6a41..76ba435a 100644 --- a/mac/mac.c +++ b/mac/mac.c @@ -1,4 +1,4 @@ -/* $Id: mac.c,v 1.24 2003/01/11 19:43:59 ben Exp $ */ +/* $Id: mac.c,v 1.25 2003/01/11 23:33:57 ben Exp $ */ /* * Copyright (c) 1999 Ben Harris * All rights reserved. @@ -169,13 +169,21 @@ static void mac_startup(void) { mac_gestalts.uncvattr = (*ti)->tecUnicodeConverterFeatures; DisposeHandle((Handle)ti); } - /* MacTCP? */ - if (Gestalt(FOUR_CHAR_CODE('mtcp'), &mac_gestalts.mtcpvers) != noErr) - mac_gestalts.mtcpvers = 0; - if (mac_gestalts.mtcpvers > 0) { - if (mactcp_init() != noErr) + /* OpenTransport? */ + if (Gestalt(gestaltOpenTpt, &mac_gestalts.otptattr) != noErr || + (mac_gestalts.otptattr & gestaltOpenTptTCPPresentMask) == 0 || + ot_init() != noErr) + mac_gestalts.otptattr = 0; + if (mac_gestalts.otptattr == 0) { + /* MacTCP? */ + if (Gestalt(FOUR_CHAR_CODE('mtcp'), &mac_gestalts.mtcpvers) != noErr) mac_gestalts.mtcpvers = 0; - } + if (mac_gestalts.mtcpvers > 0) { + if (mactcp_init() != noErr) + mac_gestalts.mtcpvers = 0; + } + } else + mac_gestalts.mtcpvers = 0; /* We've been tested with the Appearance Manager */ if (mac_gestalts.apprvers != 0) @@ -623,8 +631,7 @@ void cleanup_exit(int status) if (mac_gestalts.encvvers != 0) TerminateUnicodeConverter(); #endif - if (mac_gestalts.mtcpvers != 0) - mactcp_shutdown(); + sk_cleanup(); exit(status); } diff --git a/mac/mac.h b/mac/mac.h index d0db75e7..88b02cd0 100644 --- a/mac/mac.h +++ b/mac/mac.h @@ -24,6 +24,7 @@ struct mac_gestalts { long encvvers; /* TEC version (from TECGetInfo()) */ long uncvattr; /* Unicode Converter attributes (frem TECGetInfo()) */ long mtcpvers; + long otptattr; }; extern struct mac_gestalts mac_gestalts; @@ -94,7 +95,7 @@ extern void *open_settings_r_fsp(FSSpec *); extern void init_ucs(void); /* from mtcpnet.c */ extern OSErr mactcp_init(void); -extern void mactcp_shutdown(void); +extern void mactcp_cleanup(void); extern void mactcp_poll(void); extern SockAddr mactcp_namelookup(char *, char **); extern SockAddr mactcp_nonamelookup(char *); @@ -108,6 +109,22 @@ extern Socket mactcp_register(void *, Plug); extern Socket mactcp_new(SockAddr addr, int, int, int, int, Plug); extern Socket mactcp_newlistener(char *, int, Plug, int); extern char *mactcp_addr_error(SockAddr); +/* from otnet.c */ +extern OSErr ot_init(void); +extern void ot_cleanup(void); +extern void ot_poll(void); +extern SockAddr ot_namelookup(char *, char **); +extern SockAddr ot_nonamelookup(char *); +extern void ot_getaddr(SockAddr, char *, int); +extern int ot_hostname_is_local(char *); +extern int ot_address_is_local(SockAddr); +extern int ot_addrtype(SockAddr); +extern void ot_addrcopy(SockAddr, char *); +extern void ot_addr_free(SockAddr); +extern Socket ot_register(void *, Plug); +extern Socket ot_new(SockAddr addr, int, int, int, int, Plug); +extern Socket ot_newlistener(char *, int, Plug, int); +extern char *ot_addr_error(SockAddr); #endif diff --git a/mac/macnet.c b/mac/macnet.c index 88a5cab4..d3044dda 100644 --- a/mac/macnet.c +++ b/mac/macnet.c @@ -9,7 +9,9 @@ SockAddr sk_namelookup(char *host, char **canonicalname) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_namelookup(host, canonicalname); + else if (mac_gestalts.mtcpvers != 0) return mactcp_namelookup(host, canonicalname); else return NULL; @@ -18,7 +20,9 @@ SockAddr sk_namelookup(char *host, char **canonicalname) SockAddr sk_nonamelookup(char *host) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_nonamelookup(host); + else if (mac_gestalts.mtcpvers != 0) return mactcp_nonamelookup(host); else return NULL; @@ -27,7 +31,9 @@ SockAddr sk_nonamelookup(char *host) void sk_getaddr(SockAddr addr, char *buf, int buflen) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + ot_getaddr(addr, buf, buflen); + else if (mac_gestalts.mtcpvers != 0) mactcp_getaddr(addr, buf, buflen); else *buf = '\0'; @@ -36,7 +42,9 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen) int sk_hostname_is_local(char *name) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_hostname_is_local(name); + else if (mac_gestalts.mtcpvers != 0) return mactcp_hostname_is_local(name); else return 0; @@ -45,7 +53,9 @@ int sk_hostname_is_local(char *name) int sk_address_is_local(SockAddr addr) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_address_is_local(addr); + else if (mac_gestalts.mtcpvers != 0) return mactcp_address_is_local(addr); else return 0; @@ -54,7 +64,9 @@ int sk_address_is_local(SockAddr addr) int sk_addrtype(SockAddr addr) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_addrtype(addr); + else if (mac_gestalts.mtcpvers != 0) return mactcp_addrtype(addr); else return 0; @@ -63,21 +75,27 @@ int sk_addrtype(SockAddr addr) void sk_addrcopy(SockAddr addr, char *buf) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + ot_addrcopy(addr, buf); + else if (mac_gestalts.mtcpvers != 0) mactcp_addrcopy(addr, buf); } void sk_addr_free(SockAddr addr) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + ot_addr_free(addr); + else if (mac_gestalts.mtcpvers != 0) mactcp_addr_free(addr); } Socket sk_register(void *sock, Plug plug) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_register(sock, plug); + else if (mac_gestalts.mtcpvers != 0) return mactcp_register(sock, plug); else return NULL; @@ -87,7 +105,9 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, int nodelay, Plug plug) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_new(addr, port, privport, oobinline, nodelay, plug); + else if (mac_gestalts.mtcpvers != 0) return mactcp_new(addr, port, privport, oobinline, nodelay, plug); else return NULL; @@ -96,7 +116,9 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_newlistener(srcaddr, port, plug, local_host_only); + else if (mac_gestalts.mtcpvers != 0) return mactcp_newlistener(srcaddr, port, plug, local_host_only); else return NULL; @@ -105,12 +127,23 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) char *sk_addr_error(SockAddr addr) { - if (mac_gestalts.mtcpvers != 0) + if (mac_gestalts.otptattr != 0) + return ot_addr_error(addr); + else if (mac_gestalts.mtcpvers != 0) return mactcp_addr_error(addr); else return "No TCP/IP stack installed"; } +void sk_cleanup(void) +{ + + if (mac_gestalts.otptattr != 0) + ot_cleanup(); + else if (mac_gestalts.mtcpvers != 0) + mactcp_cleanup(); +} + /* * Local Variables: * c-file-style: "simon" diff --git a/mac/mtcpnet.c b/mac/mtcpnet.c index 91b402dd..9d40051d 100644 --- a/mac/mtcpnet.c +++ b/mac/mtcpnet.c @@ -244,7 +244,7 @@ OSErr mactcp_init(void) return noErr; } -void mactcp_shutdown(void) +void mactcp_cleanup(void) { Actual_Socket s, next; diff --git a/mac/otnet.c b/mac/otnet.c new file mode 100644 index 00000000..b4314785 --- /dev/null +++ b/mac/otnet.c @@ -0,0 +1,435 @@ +/* + * Macintosh OpenTransport networking abstraction + */ + +#include +#include + +#define DEFINE_PLUG_METHOD_MACROS +#include "putty.h" +#include "network.h" +#include "mac.h" + +struct Socket_tag { + struct socket_function_table *fn; + /* other stuff... */ + char *error; + EndpointRef ep; + Plug plug; + void *private_ptr; + bufchain output_data; + int connected; + int writable; + int frozen; /* this causes readability notifications to be ignored */ + int frozen_readable; /* this means we missed at least one readability + * notification while we were frozen */ + int localhost_only; /* for listening sockets */ + char oobdata[1]; + int sending_oob; + int oobpending; /* is there OOB data available to read?*/ + int oobinline; + int pending_error; /* in case send() returns error */ + int listener; + struct Socket_tag *next; + struct Socket_tag **prev; +}; + +typedef struct Socket_tag *Actual_Socket; + +struct SockAddr_tag { + char *error; + DNSAddress address; +}; + +/* Globals */ + +static struct { + Actual_Socket socklist; +} ot; + +OSErr ot_init(void) +{ + return InitOpenTransport(); +} + +void ot_cleanup(void) +{ + Actual_Socket s; + + for (s = ot.socklist; s !=NULL; s = s->next) { + OTUnbind(s->ep); + OTCloseProvider(s->ep); + } + + CloseOpenTransport(); +} + +static char *error_string(int error) +{ + return "An error..."; +} + +SockAddr ot_namelookup(char *host, char **canonicalname) +{ + SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + + OTInitDNSAddress(&(ret->address), host); + + /* for now we'll pretend canonicalname is always just host */ + + *canonicalname = smalloc(1+strlen(host)); + strcpy(*canonicalname, host); + return ret; +} + +SockAddr ot_nonamelookup(char *host) +{ + SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + + OTInitDNSAddress(&(ret->address), host); + + return ret; +} + +void ot_getaddr(SockAddr addr, char *buf, int buflen) +{ + strncpy(buf, (addr->address).fName, buflen); +} + +/* I think "local" here really means "loopback" */ + +int ot_hostname_is_local(char *name) +{ + + return !strcmp(name, "localhost"); +} + +int ot_address_is_local(SockAddr addr) +{ + + /* FIXME */ + return FALSE; +} + +int ot_addrtype(SockAddr addr) +{ + return ADDRTYPE_IPV4; +} + +void ot_addrcopy(SockAddr addr, char *buf) +{ + +} + +void ot_addr_free(SockAddr addr) +{ + sfree(addr); +} + + +static Plug ot_tcp_plug(Socket sock, Plug p) +{ + Actual_Socket s = (Actual_Socket) sock; + Plug ret = s->plug; + if (p) + s->plug = p; + return ret; +} + +static void ot_tcp_flush(Socket s) +{ + /* + * We send data to the socket as soon as we can anyway, + * so we don't need to do anything here. :-) + */ +} + +static void ot_tcp_close(Socket s); +static int ot_tcp_write(Socket s, char const *data, int len); +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 void ot_recv(Actual_Socket s); +void ot_poll(void); + +Socket ot_register(void *sock, Plug plug) +{ + 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; + + ret = smalloc(sizeof(struct Socket_tag)); + ret->fn = &fn_table; + ret->error = NULL; + ret->plug = plug; + bufchain_init(&ret->output_data); + ret->writable = 1; /* to start with */ + ret->sending_oob = 0; + ret->frozen = 1; + ret->frozen_readable = 0; + ret->localhost_only = 0; /* unused, but best init anyway */ + ret->pending_error = 0; + ret->oobpending = FALSE; + ret->listener = 0; + + ret->ep = (EndpointRef)sock; + + /* some sort of error checking */ + + ret->oobinline = 0; + + /* Add this to the list of all sockets */ + ret->next = ot.socklist; + ret->prev = &ot.socklist; + ot.socklist = ret; + + return (Socket) ret; +} + +Socket ot_new(SockAddr addr, int port, int privport, int oobinline, + int nodelay, Plug plug) +{ + 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; + TCall connectCall; + + ret = smalloc(sizeof(struct Socket_tag)); + ret->fn = &fn_table; + ret->error = NULL; + ret->plug = plug; + bufchain_init(&ret->output_data); + ret->connected = 0; /* to start with */ + ret->writable = 0; /* to start with */ + ret->sending_oob = 0; + ret->frozen = 0; + ret->frozen_readable = 0; + ret->localhost_only = 0; /* unused, but best init anyway */ + ret->pending_error = 0; + ret->oobinline = oobinline; + ret->oobpending = FALSE; + ret->listener = 0; + + /* Open Endpoint, configure it for TCP over anything */ + + ep = OTOpenEndpoint(OTCreateConfiguration("tcp"), 0, NULL, &err); + + ret->ep = ep; + + if (err) { + ret->error = error_string(err); + return (Socket) ret; + } + + /* TODO: oobinline, nodelay */ + + /* + * Bind to local address. + */ + + /* FIXME: pay attention to privport */ + + err = OTBind(ep, NULL, NULL); /* OpenTransport always picks our address */ + + if (err) { + ret->error = error_string(err); + return (Socket) ret; + } + + /* + * Connect to remote address. + */ + + /* FIXME: bolt the port onto the end */ + + OTMemzero(&connectCall, sizeof(TCall)); + connectCall.addr.buf = (UInt8 *) &(addr->address); + connectCall.addr.len = sizeof(DNSAddress); + + err = OTConnect(ep, &connectCall, nil); + + if (err) { + ret->error = error_string(err); + return (Socket) ret; + } else { + ret->connected = 1; + ret->writable = 1; + } + + /* Add this to the list of all sockets */ + ret->next = ot.socklist; + ret->prev = &ot.socklist; + ot.socklist = ret; + + return (Socket) ret; +} + +Socket ot_newlistener(char *foobar, int port, Plug plug, int local_host_only) +{ + Actual_Socket s; + + return (Socket) s; +} + +static void ot_tcp_close(Socket sock) +{ + Actual_Socket s = (Actual_Socket) sock; + + OTCloseProvider(s->ep); + + /* Unhitch from list of sockets */ + *s->prev = s->next; + if (s->next != NULL) + s->next->prev = s->prev; + + sfree(s); +} + +static void try_send(Actual_Socket s) +{ + while (bufchain_size(&s->output_data) > 0) { + int nsent; + void *data; + int len; + + /* Don't care about oob right now */ + + bufchain_prefix(&s->output_data, &data, &len); + + nsent = OTSnd(s->ep, data, len, 0); + noise_ultralight(nsent); + + if (nsent <= 0) { + /* something bad happened, hey ho */ + } else { + /* still don't care about oob */ + bufchain_consume(&s->output_data, nsent); + } + } +} + +static int ot_tcp_write(Socket sock, char const *buf, int len) +{ + Actual_Socket s = (Actual_Socket) sock; + + bufchain_add(&s->output_data, buf, len); + + if (s->writable) + try_send(s); + return bufchain_size(&s->output_data); +} + +static int ot_tcp_write_oob(Socket sock, char const *buf, int len) +{ + /* Don't care about oob */ + return 0; +} + + +/* + * Each socket abstraction contains a `void *' private field in + * which the client can keep state. + */ +static void ot_tcp_set_private_ptr(Socket sock, void *ptr) +{ + Actual_Socket s = (Actual_Socket) sock; + s->private_ptr = ptr; +} + +static void *ot_tcp_get_private_ptr(Socket sock) +{ + Actual_Socket s = (Actual_Socket) sock; + return s->private_ptr; +} + + +/* + * Special error values are returned from ot_namelookup and ot_new + * if there's a problem. These functions extract an error message, + * or return NULL if there's no problem. + */ +char *ot_addr_error(SockAddr addr) +{ + return addr->error; +} +static char *ot_tcp_socket_error(Socket sock) +{ + Actual_Socket s = (Actual_Socket) sock; + return s->error; +} + +static void ot_tcp_set_frozen(Socket sock, int is_frozen) +{ + Actual_Socket s = (Actual_Socket) sock; + + if (s->frozen == is_frozen) + return; + s->frozen = is_frozen; +} + +/* + * Poll all our sockets from an event loop + */ + +void ot_poll(void) +{ + Actual_Socket s; + OTResult o; + + for (s = ot.socklist; s != NULL; s = s->next) { + o = OTLook(s->ep); + + switch(o) { + case T_DATA: /* Normal Data */ + ot_recv(s); + break; + case T_EXDATA: /* Expedited Data (urgent?) */ + ot_recv(s); + break; + } + } +} + +void ot_recv(Actual_Socket s) +{ + OTResult o; + char buf[20480]; + OTFlags flags; + + if (s->frozen) return; + + while ((o = OTRcv(s->ep, buf, sizeof(buf), &flags)) != kOTNoDataErr) { + plug_receive(s->plug, 0, buf, sizeof(buf)); + } +} + + +/* + * Local Variables: + * c-file-style: "simon" + * End: + */ diff --git a/mkfiles.pl b/mkfiles.pl index 74ffc0b9..206c39bd 100755 --- a/mkfiles.pl +++ b/mkfiles.pl @@ -622,6 +622,9 @@ Libs_68K = "{CLibraries}StdCLib.far.o" \xb6 "{Libraries}MathLib.far.o" \xb6 "{Libraries}IntEnv.far.o" \xb6 "{Libraries}Interface.o" \xb6 + "{Libraries}OpenTransport.o" \xb6 + "{Libraries}OpenTransportApp.o" \xb6 + "{Libraries}OpenTptInet.o" \xb6 "{Libraries}UnicodeConverterLib.far.o" Libs_CFM = "{SharedLibraries}InterfaceLib" \xb6 @@ -641,9 +644,17 @@ Libs_PPC = {Libs_CFM} \xb6 -weaklib ControlsLib \xb6 "{SharedLibraries}WindowsLib" \xb6 -weaklib WindowsLib \xb6 + "{SharedLibraries}OpenTransportLib" \xb6 + -weaklib OTClientLib \xb6 + -weaklib OTClientUtilLib \xb6 + -weaklib OTUtilityLib \xb6 + "{SharedLibraries}OpenTptInternetLib" \xb6 + -weaklib OTInetClientLib \xb6 "{PPCLibraries}StdCRuntime.o" \xb6 "{PPCLibraries}PPCCRuntime.o" \xb6 - "{PPCLibraries}CarbonAccessors.o" + "{PPCLibraries}CarbonAccessors.o" \xb6 + "{PPCLibraries}OpenTransportAppPPC.o" \xb6 + "{PPCLibraries}OpenTptInetPPC.o" END print &splitline("all \xc4 " . join(" ", &progrealnames("M")), undef, "\xb6");