2 * Macintosh OpenTransport networking abstraction
5 #include <OpenTransport.h>
6 #include <OpenTptInternet.h>
8 #define DEFINE_PLUG_METHOD_MACROS
14 struct socket_function_table *fn;
23 int frozen; /* this causes readability notifications to be ignored */
24 int frozen_readable; /* this means we missed at least one readability
25 * notification while we were frozen */
26 int localhost_only; /* for listening sockets */
29 int oobpending; /* is there OOB data available to read?*/
31 int pending_error; /* in case send() returns error */
33 struct Socket_tag *next;
34 struct Socket_tag **prev;
37 typedef struct Socket_tag *Actual_Socket;
47 Actual_Socket socklist;
52 return InitOpenTransport();
59 for (s = ot.socklist; s !=NULL; s = s->next) {
61 OTCloseProvider(s->ep);
67 SockAddr ot_namelookup(char *host, char **canonicalname)
69 SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
71 ret->error = kOTNoError;
72 OTInitDNSAddress(&(ret->address), host);
74 /* for now we'll pretend canonicalname is always just host */
76 *canonicalname = smalloc(1+strlen(host));
77 strcpy(*canonicalname, host);
81 SockAddr ot_nonamelookup(char *host)
83 SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
85 OTInitDNSAddress(&(ret->address), host);
90 void ot_getaddr(SockAddr addr, char *buf, int buflen)
92 strncpy(buf, (addr->address).fName, buflen);
95 /* I think "local" here really means "loopback" */
97 int ot_hostname_is_local(char *name)
100 return !strcmp(name, "localhost");
103 int ot_address_is_local(SockAddr addr)
110 int ot_addrtype(SockAddr addr)
112 return ADDRTYPE_IPV4;
115 void ot_addrcopy(SockAddr addr, char *buf)
120 void ot_addr_free(SockAddr addr)
126 static Plug ot_tcp_plug(Socket sock, Plug p)
128 Actual_Socket s = (Actual_Socket) sock;
135 static void ot_tcp_flush(Socket s)
138 * We send data to the socket as soon as we can anyway,
139 * so we don't need to do anything here. :-)
143 static void ot_tcp_close(Socket s);
144 static int ot_tcp_write(Socket s, char const *data, int len);
145 static int ot_tcp_write_oob(Socket s, char const *data, int len);
146 static void ot_tcp_set_private_ptr(Socket s, void *ptr);
147 static void *ot_tcp_get_private_ptr(Socket s);
148 static void ot_tcp_set_frozen(Socket s, int is_frozen);
149 static char *ot_tcp_socket_error(Socket s);
150 static void ot_recv(Actual_Socket s);
153 Socket ot_register(void *sock, Plug plug)
155 static struct socket_function_table fn_table = {
161 ot_tcp_set_private_ptr,
162 ot_tcp_get_private_ptr,
169 ret = smalloc(sizeof(struct Socket_tag));
171 ret->error = kOTNoError;
173 bufchain_init(&ret->output_data);
174 ret->writable = 1; /* to start with */
175 ret->sending_oob = 0;
177 ret->frozen_readable = 0;
178 ret->localhost_only = 0; /* unused, but best init anyway */
179 ret->pending_error = 0;
180 ret->oobpending = FALSE;
183 ret->ep = (EndpointRef)sock;
185 /* some sort of error checking */
189 /* Add this to the list of all sockets */
190 ret->next = ot.socklist;
191 ret->prev = &ot.socklist;
197 Socket ot_new(SockAddr addr, int port, int privport, int oobinline,
198 int nodelay, Plug plug)
200 static struct socket_function_table fn_table = {
206 ot_tcp_set_private_ptr,
207 ot_tcp_get_private_ptr,
217 ret = smalloc(sizeof(struct Socket_tag));
219 ret->error = kOTNoError;
221 bufchain_init(&ret->output_data);
222 ret->connected = 0; /* to start with */
223 ret->writable = 0; /* to start with */
224 ret->sending_oob = 0;
226 ret->frozen_readable = 0;
227 ret->localhost_only = 0; /* unused, but best init anyway */
228 ret->pending_error = 0;
229 ret->oobinline = oobinline;
230 ret->oobpending = FALSE;
233 /* Open Endpoint, configure it for TCP over anything */
235 ep = OTOpenEndpoint(OTCreateConfiguration("tcp"), 0, NULL, &err);
244 /* TODO: oobinline, nodelay */
247 * Bind to local address.
250 /* FIXME: pay attention to privport */
252 err = OTBind(ep, NULL, NULL); /* OpenTransport always picks our address */
260 * Connect to remote address.
263 /* FIXME: bolt the port onto the end */
265 OTMemzero(&connectCall, sizeof(TCall));
266 connectCall.addr.buf = (UInt8 *) &(addr->address);
267 connectCall.addr.len = sizeof(DNSAddress);
269 err = OTConnect(ep, &connectCall, nil);
279 /* Add this to the list of all sockets */
280 ret->next = ot.socklist;
281 ret->prev = &ot.socklist;
287 Socket ot_newlistener(char *foobar, int port, Plug plug, int local_host_only)
294 static void ot_tcp_close(Socket sock)
296 Actual_Socket s = (Actual_Socket) sock;
298 OTCloseProvider(s->ep);
300 /* Unhitch from list of sockets */
303 s->next->prev = s->prev;
308 static void try_send(Actual_Socket s)
310 while (bufchain_size(&s->output_data) > 0) {
315 /* Don't care about oob right now */
317 bufchain_prefix(&s->output_data, &data, &len);
319 nsent = OTSnd(s->ep, data, len, 0);
320 noise_ultralight(nsent);
323 /* something bad happened, hey ho */
325 /* still don't care about oob */
326 bufchain_consume(&s->output_data, nsent);
331 static int ot_tcp_write(Socket sock, char const *buf, int len)
333 Actual_Socket s = (Actual_Socket) sock;
335 bufchain_add(&s->output_data, buf, len);
339 return bufchain_size(&s->output_data);
342 static int ot_tcp_write_oob(Socket sock, char const *buf, int len)
344 /* Don't care about oob */
350 * Each socket abstraction contains a `void *' private field in
351 * which the client can keep state.
353 static void ot_tcp_set_private_ptr(Socket sock, void *ptr)
355 Actual_Socket s = (Actual_Socket) sock;
356 s->private_ptr = ptr;
359 static void *ot_tcp_get_private_ptr(Socket sock)
361 Actual_Socket s = (Actual_Socket) sock;
362 return s->private_ptr;
367 * Special error values are returned from ot_namelookup and ot_new
368 * if there's a problem. These functions extract an error message,
369 * or return NULL if there's no problem.
371 char *ot_addr_error(SockAddr addr)
373 static char buf[128];
375 if (addr->error == kOTNoError)
377 sprintf(buf, "error %d", addr->error);
380 static char *ot_tcp_socket_error(Socket sock)
382 Actual_Socket s = (Actual_Socket) sock;
383 static char buf[128];
385 if (s->error == kOTNoError)
387 sprintf(buf, "error %d", s->error);
391 static void ot_tcp_set_frozen(Socket sock, int is_frozen)
393 Actual_Socket s = (Actual_Socket) sock;
395 if (s->frozen == is_frozen)
397 s->frozen = is_frozen;
401 * Poll all our sockets from an event loop
409 for (s = ot.socklist; s != NULL; s = s->next) {
413 case T_DATA: /* Normal Data */
416 case T_EXDATA: /* Expedited Data (urgent?) */
423 void ot_recv(Actual_Socket s)
429 if (s->frozen) return;
431 while ((o = OTRcv(s->ep, buf, sizeof(buf), &flags)) != kOTNoDataErr) {
432 plug_receive(s->plug, 0, buf, sizeof(buf));
439 * c-file-style: "simon"