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 static char *error_string(int error
)
72 SockAddr
ot_namelookup(char *host
, char **canonicalname
)
74 SockAddr ret
= smalloc(sizeof(struct SockAddr_tag
));
76 OTInitDNSAddress(&(ret
->address
), host
);
78 /* for now we'll pretend canonicalname is always just host */
80 *canonicalname
= smalloc(1+strlen(host
));
81 strcpy(*canonicalname
, host
);
85 SockAddr
ot_nonamelookup(char *host
)
87 SockAddr ret
= smalloc(sizeof(struct SockAddr_tag
));
89 OTInitDNSAddress(&(ret
->address
), host
);
94 void ot_getaddr(SockAddr addr
, char *buf
, int buflen
)
96 strncpy(buf
, (addr
->address
).fName
, buflen
);
99 /* I think "local" here really means "loopback" */
101 int ot_hostname_is_local(char *name
)
104 return !strcmp(name
, "localhost");
107 int ot_address_is_local(SockAddr addr
)
114 int ot_addrtype(SockAddr addr
)
116 return ADDRTYPE_IPV4
;
119 void ot_addrcopy(SockAddr addr
, char *buf
)
124 void ot_addr_free(SockAddr addr
)
130 static Plug
ot_tcp_plug(Socket sock
, Plug p
)
132 Actual_Socket s
= (Actual_Socket
) sock
;
139 static void ot_tcp_flush(Socket s
)
142 * We send data to the socket as soon as we can anyway,
143 * so we don't need to do anything here. :-)
147 static void ot_tcp_close(Socket s
);
148 static int ot_tcp_write(Socket s
, char const *data
, int len
);
149 static int ot_tcp_write_oob(Socket s
, char const *data
, int len
);
150 static void ot_tcp_set_private_ptr(Socket s
, void *ptr
);
151 static void *ot_tcp_get_private_ptr(Socket s
);
152 static void ot_tcp_set_frozen(Socket s
, int is_frozen
);
153 static char *ot_tcp_socket_error(Socket s
);
154 static void ot_recv(Actual_Socket s
);
157 Socket
ot_register(void *sock
, Plug plug
)
159 static struct socket_function_table fn_table
= {
165 ot_tcp_set_private_ptr
,
166 ot_tcp_get_private_ptr
,
173 ret
= smalloc(sizeof(struct Socket_tag
));
177 bufchain_init(&ret
->output_data
);
178 ret
->writable
= 1; /* to start with */
179 ret
->sending_oob
= 0;
181 ret
->frozen_readable
= 0;
182 ret
->localhost_only
= 0; /* unused, but best init anyway */
183 ret
->pending_error
= 0;
184 ret
->oobpending
= FALSE
;
187 ret
->ep
= (EndpointRef
)sock
;
189 /* some sort of error checking */
193 /* Add this to the list of all sockets */
194 ret
->next
= ot
.socklist
;
195 ret
->prev
= &ot
.socklist
;
201 Socket
ot_new(SockAddr addr
, int port
, int privport
, int oobinline
,
202 int nodelay
, Plug plug
)
204 static struct socket_function_table fn_table
= {
210 ot_tcp_set_private_ptr
,
211 ot_tcp_get_private_ptr
,
221 ret
= smalloc(sizeof(struct Socket_tag
));
225 bufchain_init(&ret
->output_data
);
226 ret
->connected
= 0; /* to start with */
227 ret
->writable
= 0; /* to start with */
228 ret
->sending_oob
= 0;
230 ret
->frozen_readable
= 0;
231 ret
->localhost_only
= 0; /* unused, but best init anyway */
232 ret
->pending_error
= 0;
233 ret
->oobinline
= oobinline
;
234 ret
->oobpending
= FALSE
;
237 /* Open Endpoint, configure it for TCP over anything */
239 ep
= OTOpenEndpoint(OTCreateConfiguration("tcp"), 0, NULL
, &err
);
244 ret
->error
= error_string(err
);
248 /* TODO: oobinline, nodelay */
251 * Bind to local address.
254 /* FIXME: pay attention to privport */
256 err
= OTBind(ep
, NULL
, NULL
); /* OpenTransport always picks our address */
259 ret
->error
= error_string(err
);
264 * Connect to remote address.
267 /* FIXME: bolt the port onto the end */
269 OTMemzero(&connectCall
, sizeof(TCall
));
270 connectCall
.addr
.buf
= (UInt8
*) &(addr
->address
);
271 connectCall
.addr
.len
= sizeof(DNSAddress
);
273 err
= OTConnect(ep
, &connectCall
, nil
);
276 ret
->error
= error_string(err
);
283 /* Add this to the list of all sockets */
284 ret
->next
= ot
.socklist
;
285 ret
->prev
= &ot
.socklist
;
291 Socket
ot_newlistener(char *foobar
, int port
, Plug plug
, int local_host_only
)
298 static void ot_tcp_close(Socket sock
)
300 Actual_Socket s
= (Actual_Socket
) sock
;
302 OTCloseProvider(s
->ep
);
304 /* Unhitch from list of sockets */
307 s
->next
->prev
= s
->prev
;
312 static void try_send(Actual_Socket s
)
314 while (bufchain_size(&s
->output_data
) > 0) {
319 /* Don't care about oob right now */
321 bufchain_prefix(&s
->output_data
, &data
, &len
);
323 nsent
= OTSnd(s
->ep
, data
, len
, 0);
324 noise_ultralight(nsent
);
327 /* something bad happened, hey ho */
329 /* still don't care about oob */
330 bufchain_consume(&s
->output_data
, nsent
);
335 static int ot_tcp_write(Socket sock
, char const *buf
, int len
)
337 Actual_Socket s
= (Actual_Socket
) sock
;
339 bufchain_add(&s
->output_data
, buf
, len
);
343 return bufchain_size(&s
->output_data
);
346 static int ot_tcp_write_oob(Socket sock
, char const *buf
, int len
)
348 /* Don't care about oob */
354 * Each socket abstraction contains a `void *' private field in
355 * which the client can keep state.
357 static void ot_tcp_set_private_ptr(Socket sock
, void *ptr
)
359 Actual_Socket s
= (Actual_Socket
) sock
;
360 s
->private_ptr
= ptr
;
363 static void *ot_tcp_get_private_ptr(Socket sock
)
365 Actual_Socket s
= (Actual_Socket
) sock
;
366 return s
->private_ptr
;
371 * Special error values are returned from ot_namelookup and ot_new
372 * if there's a problem. These functions extract an error message,
373 * or return NULL if there's no problem.
375 char *ot_addr_error(SockAddr addr
)
379 static char *ot_tcp_socket_error(Socket sock
)
381 Actual_Socket s
= (Actual_Socket
) sock
;
385 static void ot_tcp_set_frozen(Socket sock
, int is_frozen
)
387 Actual_Socket s
= (Actual_Socket
) sock
;
389 if (s
->frozen
== is_frozen
)
391 s
->frozen
= is_frozen
;
395 * Poll all our sockets from an event loop
403 for (s
= ot
.socklist
; s
!= NULL
; s
= s
->next
) {
407 case T_DATA
: /* Normal Data */
410 case T_EXDATA
: /* Expedited Data (urgent?) */
417 void ot_recv(Actual_Socket s
)
423 if (s
->frozen
) return;
425 while ((o
= OTRcv(s
->ep
, buf
, sizeof(buf
), &flags
)) != kOTNoDataErr
) {
426 plug_receive(s
->plug
, 0, buf
, sizeof(buf
));
433 * c-file-style: "simon"