]> git.saurik.com Git - wxWidgets.git/blame - src/mac/gsocket.c
Under Cygwin, in platform.h default to wxMSW unless otherwise specified.
[wxWidgets.git] / src / mac / gsocket.c
CommitLineData
ee6b1d97
SC
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Authors: Guilhem Lavaux,
5 * Guillermo Rodriguez Garcia <guille@iies.es> (maintainer)
6 * Stefan CSomor
7 * Purpose: GSocket main mac file
8 * CVSID: $Id$
9 * -------------------------------------------------------------------------
10 */
11
12/*
13 * PLEASE don't put C++ comments here - this is a C source file.
14 */
15
16#ifndef __GSOCKET_STANDALONE__
17#include "wx/setup.h"
4ed09051 18#include "wx/platform.h"
ee6b1d97
SC
19#endif
20
21#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
22
f5c6eb5c 23#ifdef __DARWIN__
5fde6fcc 24 #include <CoreServices/CoreServices.h>
03e11df5
GD
25
26 #ifndef FALSE
27 #define FALSE 0
28 #endif
29 #ifndef TRUE
30 #define TRUE 1
31 #endif
32#else
76a5e5d2 33 #include <MacHeaders.c>
5fde6fcc 34 #define OTUNIXERRORS 1
03e11df5
GD
35 #include <OpenTransport.h>
36 #include <OpenTransportProviders.h>
37 #include <OpenTptInternet.h>
38#endif
39#if TARGET_CARBON
40 #define OTAssert( str , cond ) /* does not exists in Carbon */
41#endif
42
ee6b1d97
SC
43#include <assert.h>
44#include <errno.h>
45#include <string.h>
46#include <unistd.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <stddef.h>
50#include <ctype.h>
ee6b1d97
SC
51#include <utime.h>
52
53/*
54 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
55 * on all unices. INADDR_BROADCAST should be fine to indicate an error.
56 */
57#ifndef INADDR_BROADCAST
58#define INADDR_BROADCAST 0xFFFFFFFFUL
59#endif
60#ifndef INADDR_NONE
61#define INADDR_NONE INADDR_BROADCAST
62#endif
63#ifndef INADDR_ANY
64#define INADDR_ANY 0x0UL
65#endif
66#ifndef __GSOCKET_STANDALONE__
67
68#include "wx/mac/macnotfy.h"
69#include "wx/mac/gsockmac.h"
70#include "wx/gsocket.h"
71
72#else
73
74#include "gsockmac.h"
75#include "gsocket.h"
76
77#endif /* __GSOCKET_STANDALONE__ */
78
79void wxCYield() ;
80#ifdef __WXDEBUG__
81#define qDebug 1
82#define qDebug2 1
83extern pascal void OTDebugStr(const char* str);
84#endif
f5c6eb5c 85#ifndef __DARWIN__
03e11df5
GD
86 #include <OTDebug.h>
87#endif
ee6b1d97 88InetSvcRef gInetSvcRef = 0 ;
fb606749 89int gOTInited = 0 ;
2b5f62a0 90OTNotifyUPP gOTNotifierUPP = NULL ;
ee6b1d97
SC
91
92OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode);
93
94/* Input: ep - endpointref on which to negotiate the option
95 enableReuseIPMode - desired option setting - true/false
96 Return: kOTNoError indicates that the option was successfully negotiated
97 OSStatus is an error if < 0, otherwise, the status field is
98 returned and is > 0.
99
100 IMPORTANT NOTE: The endpoint is assumed to be in synchronous more, otherwise
101 this code will not function as desired
102*/
103
104
105OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode)
106
107{
108 UInt8 buf[kOTFourByteOptionSize]; // define buffer for fourByte Option size
109 TOption* opt; // option ptr to make items easier to access
110 TOptMgmt req;
111 TOptMgmt ret;
112 OSStatus err;
113
114 if (!OTIsSynchronous(ep))
115 {
116 return (-1);
117 }
118 opt = (TOption*)buf; // set option ptr to buffer
119 req.opt.buf = buf;
120 req.opt.len = sizeof(buf);
121 req.flags = T_NEGOTIATE; // negotiate for option
122
123 ret.opt.buf = buf;
124 ret.opt.maxlen = kOTFourByteOptionSize;
125
126 opt->level = INET_IP; // dealing with an IP Level function
f5c6eb5c 127#ifdef __DARWIN__
5fde6fcc
GD
128 opt->name = kIP_REUSEADDR;
129#else
ee6b1d97 130 opt->name = IP_REUSEADDR;
5fde6fcc 131#endif
ee6b1d97
SC
132 opt->len = kOTFourByteOptionSize;
133 opt->status = 0;
134 *(UInt32*)opt->value = enableReuseIPMode; // set the desired option level, true or false
135
136 err = OTOptionManagement(ep, &req, &ret);
137
138 // if no error then return the option status value
139 if (err == kOTNoError)
140 {
141 if (opt->status != T_SUCCESS)
142 err = opt->status;
143 else
144 err = kOTNoError;
145 }
146
147 return err;
148}
149
150
151pascal void OTInetEventHandler(void*s, OTEventCode event, OTResult, void *cookie) ;
152pascal void OTInetEventHandler(void*s, OTEventCode event, OTResult result, void *cookie)
153{
154 int wakeUp = true ;
155 GSocket* sock = (GSocket*) s ;
156
157 if ( event == kOTSyncIdleEvent )
158 {
159 YieldToAnyThread() ;
160 return ;
161 }
162
163 if ( s )
164 {
165 wxMacAddEvent( sock->m_mac_events , _GSocket_Internal_Proc , event , s , wakeUp ) ;
166 }
167
168 return;
169}
170
171static void SetDefaultEndpointModes(EndpointRef ep , void *data )
172 // This routine sets the supplied endpoint into the default
173 // mode used in this application. The specifics are:
174 // blocking, synchronous, and using synch idle events with
175 // the standard YieldingNotifier.
176{
177 OSStatus junk = kOTNoError ;
178 OTAssert ("SetDefaultEndpointModes:invalid ref", ep != kOTInvalidEndpointRef ) ;
179 junk = OTSetAsynchronous(ep);
180 OTAssert("SetDefaultEndpointModes: Could not set asynchronous", junk == noErr);
181/*
182 junk = OTSetBlocking(ep);
183 OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr);
184 junk = OTSetSynchronous(ep);
185 OTAssert("SetDefaultEndpointModes: Could not set synchronous", junk == noErr);
186 junk = OTSetBlocking(ep);
187 OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr);
188*/
2b5f62a0 189 junk = OTInstallNotifier(ep, gOTNotifierUPP, data);
ee6b1d97
SC
190 OTAssert("SetDefaultEndpointModes: Could not install notifier", junk == noErr);
191/*
192 junk = OTUseSyncIdleEvents(ep, true);
193 OTAssert("SetDefaultEndpointModes: Could not use sync idle events", junk == noErr);
194*/
195}
196
197/* Global initialisers */
198
199int GSocket_Init()
79da3092
SC
200{
201 return TRUE;
202}
203
204int GSocket_Verify_Inited() ;
205int GSocket_Verify_Inited()
ee6b1d97 206{
b97e22c0 207 OSStatus err ;
ee6b1d97 208#if TARGET_CARBON
b97e22c0
GD
209 // Marc Newsam: added the clientcontext variable
210 // however, documentation is unclear how this works
211 OTClientContextPtr clientcontext;
212
79da3092
SC
213 if ( gInetSvcRef )
214 return TRUE ;
215
b97e22c0 216 InitOpenTransportInContext(kInitOTForApplicationMask, &clientcontext);
fb606749 217 gOTInited = 1 ;
b97e22c0
GD
218 gInetSvcRef = OTOpenInternetServicesInContext(kDefaultInternetServicesPath,
219 NULL, &err, clientcontext);
ee6b1d97 220#else
79da3092
SC
221 if ( gInetSvcRef )
222 return TRUE ;
223
b97e22c0 224 InitOpenTransport() ;
fb606749 225 gOTInited = 1 ;
b97e22c0 226 gInetSvcRef = OTOpenInternetServices(kDefaultInternetServicesPath, NULL, &err);
ee6b1d97 227#endif
b97e22c0
GD
228 if ( gInetSvcRef == NULL || err != kOTNoError )
229 {
230 OTAssert("Could not open Inet Services", err == noErr);
231 return FALSE ;
232 }
2b5f62a0 233 gOTNotifierUPP = NewOTNotifyUPP( OTInetEventHandler ) ;
79da3092 234 return TRUE ;
ee6b1d97
SC
235}
236
237void GSocket_Cleanup()
238{
fb606749
SC
239 if ( gOTInited != 0 )
240 {
241 if ( gInetSvcRef != NULL )
242 OTCloseProvider( gInetSvcRef );
243 #if TARGET_CARBON
244 CloseOpenTransportInContext( NULL ) ;
245 #else
246 CloseOpenTransport() ;
247 #endif
2b5f62a0
VZ
248 if ( gOTNotifierUPP )
249 DisposeOTNotifyUPP( gOTNotifierUPP ) ;
fb606749 250 }
ee6b1d97
SC
251}
252
253/* Constructors / Destructors for GSocket */
254
255GSocket *GSocket_new()
256{
79da3092 257
ee6b1d97
SC
258 int i;
259 GSocket *socket;
260
79da3092
SC
261 if ( GSocket_Verify_Inited() == FALSE )
262 return NULL ;
263
ee6b1d97
SC
264 socket = (GSocket *)malloc(sizeof(GSocket));
265
266 if (socket == NULL)
267 return NULL;
268
269 socket->m_endpoint = NULL ;
270 for (i=0;i<GSOCK_MAX_EVENT;i++)
271 {
272 socket->m_cbacks[i] = NULL;
273 }
274 socket->m_detected = 0;
275 socket->m_local = NULL;
276 socket->m_peer = NULL;
277 socket->m_error = GSOCK_NOERROR;
278 socket->m_server = FALSE;
279 socket->m_stream = TRUE;
280 socket->m_non_blocking = FALSE;
62e83765 281 socket->m_timeout = 1*1000;
79da3092 282 /* 10 sec * 1000 millisec */
ee6b1d97
SC
283 socket->m_takesEvents = TRUE ;
284 socket->m_mac_events = wxMacGetNotifierTable() ;
285 return socket;
286}
287
288void GSocket_destroy(GSocket *socket)
289{
290 assert(socket != NULL);
291
292 /* Check that the socket is really shutdowned */
293 if (socket->m_endpoint != kOTInvalidEndpointRef)
294 GSocket_Shutdown(socket);
295
296
297 /* Destroy private addresses */
298 if (socket->m_local)
299 GAddress_destroy(socket->m_local);
300
301 if (socket->m_peer)
302 GAddress_destroy(socket->m_peer);
303
304 /* Destroy the socket itself */
305 free(socket);
306}
307
308/* GSocket_Shutdown:
309 * Disallow further read/write operations on this socket, close
310 * the fd and disable all callbacks.
311 */
312void GSocket_Shutdown(GSocket *socket)
313{
314 OSStatus err ;
315 int evt;
316
317 assert(socket != NULL);
318
319 /* If socket has been created, shutdown it */
320 if (socket->m_endpoint != kOTInvalidEndpointRef )
321 {
322 err = OTSndOrderlyDisconnect( socket->m_endpoint ) ;
323 if ( err != kOTNoError )
324 {
325
326 }
327 err = OTRcvOrderlyDisconnect( socket->m_endpoint ) ;
328 err = OTUnbind( socket->m_endpoint ) ;
329 err = OTCloseProvider( socket->m_endpoint ) ;
330 socket->m_endpoint = kOTInvalidEndpointRef ;
331 }
332
333 /* Disable GUI callbacks */
334 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
335 socket->m_cbacks[evt] = NULL;
336
337 socket->m_detected = 0;
338 _GSocket_Disable_Events(socket);
339 wxMacRemoveAllNotifiersForData( wxMacGetNotifierTable() , socket ) ;
340}
341
342
343/* Address handling */
344
345/* GSocket_SetLocal:
346 * GSocket_GetLocal:
347 * GSocket_SetPeer:
348 * GSocket_GetPeer:
349 * Set or get the local or peer address for this socket. The 'set'
350 * functions return GSOCK_NOERROR on success, an error code otherwise.
351 * The 'get' functions return a pointer to a GAddress object on success,
352 * or NULL otherwise, in which case they set the error code of the
353 * corresponding GSocket.
354 *
355 * Error codes:
356 * GSOCK_INVSOCK - the socket is not valid.
357 * GSOCK_INVADDR - the address is not valid.
358 */
359GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
360{
361 assert(socket != NULL);
362
363 /* the socket must be initialized, or it must be a server */
364 if ((socket->m_endpoint != kOTInvalidEndpointRef && !socket->m_server))
365 {
366 socket->m_error = GSOCK_INVSOCK;
367 return GSOCK_INVSOCK;
368 }
369
370 /* check address */
371 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
372 {
373 socket->m_error = GSOCK_INVADDR;
374 return GSOCK_INVADDR;
375 }
376
377 if (socket->m_local)
378 GAddress_destroy(socket->m_local);
379
380 socket->m_local = GAddress_copy(address);
381
382 return GSOCK_NOERROR;
383}
384
385GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
386{
387 assert(socket != NULL);
388
389 /* check address */
390 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
391 {
392 socket->m_error = GSOCK_INVADDR;
393 return GSOCK_INVADDR;
394 }
395
396 if (socket->m_peer)
397 GAddress_destroy(socket->m_peer);
398
399 socket->m_peer = GAddress_copy(address);
400
401 return GSOCK_NOERROR;
402}
403
404GAddress *GSocket_GetLocal(GSocket *socket)
405{
406 GAddress *address = NULL ;
ee6b1d97
SC
407 GSocketError err;
408 InetAddress loc ;
409
410 assert(socket != NULL);
411
412 /* try to get it from the m_local var first */
413 if (socket->m_local)
414 return GAddress_copy(socket->m_local);
415
416 /* else, if the socket is initialized, try getsockname */
417 if (socket->m_endpoint == kOTInvalidEndpointRef)
418 {
419 socket->m_error = GSOCK_INVSOCK;
420 return NULL;
421 }
422
423
424/* we do not support multihoming with this code at the moment
425 OTGetProtAddress will have to be used then - but we don't have a handy
426 method to use right now
427*/
428 {
429 InetInterfaceInfo info;
430 OTInetGetInterfaceInfo(&info, kDefaultInetInterface);
431 loc.fHost = info.fAddress ;
432 loc.fPort = 0 ;
433 loc.fAddressType = AF_INET ;
434 }
435
436 /* got a valid address from getsockname, create a GAddress object */
437 address = GAddress_new();
438 if (address == NULL)
439 {
440 socket->m_error = GSOCK_MEMERR;
441 return NULL;
442 }
443
444 err = _GAddress_translate_from(address, &loc);
445 if (err != GSOCK_NOERROR)
446 {
447 GAddress_destroy(address);
448 socket->m_error = err;
449 return NULL;
450 }
451
452 return address;
453}
454
455GAddress *GSocket_GetPeer(GSocket *socket)
456{
457 assert(socket != NULL);
458
459 /* try to get it from the m_peer var */
460 if (socket->m_peer)
461 return GAddress_copy(socket->m_peer);
462
463 return NULL;
464}
465
466/* Server specific parts */
467
468/* GSocket_SetServer:
469 * Sets up this socket as a server. The local address must have been
470 * set with GSocket_SetLocal() before GSocket_SetServer() is called.
471 * Returns GSOCK_NOERROR on success, one of the following otherwise:
472 *
473 * Error codes:
474 * GSOCK_INVSOCK - the socket is in use.
475 * GSOCK_INVADDR - the local address has not been set.
476 * GSOCK_IOERR - low-level error.
477 */
478GSocketError GSocket_SetServer(GSocket *sck)
479{
ee6b1d97
SC
480 assert(sck != NULL);
481
482 /* must not be in use */
483 if (sck->m_endpoint != kOTInvalidEndpointRef )
484 {
485 sck->m_error = GSOCK_INVSOCK;
486 return GSOCK_INVSOCK;
487 }
488
489 /* the local addr must have been set */
490 if (!sck->m_local)
491 {
492 sck->m_error = GSOCK_INVADDR;
493 return GSOCK_INVADDR;
494 }
495
496 /* Initialize all fields */
497 sck->m_stream = TRUE;
498 sck->m_server = TRUE;
499 sck->m_oriented = TRUE;
500
501// TODO
502#if 0
503 /* Create the socket */
504 sck->m_endpoint = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
505 socket_set_ref( sck->m_endpoint , (unsigned long) &gMacNetEvents , (unsigned long) sck ) ;
506 if (sck->m_endpoint == kOTInvalidEndpointRef)
507 {
508 sck->m_error = GSOCK_IOERR;
509 return GSOCK_IOERR;
510 }
511
512 ioctl(sck->m_endpoint, FIONBIO, &arg);
513 _GSocket_Enable_Events(sck);
514
515 /* Bind to the local address,
516 * retrieve the actual address bound,
517 * and listen up to 5 connections.
518 */
519 if ((bind(sck->m_endpoint, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
520 (getsockname(sck->m_endpoint,
521 sck->m_local->m_addr,
522 (SOCKLEN_T *) &sck->m_local->m_len) != 0) ||
523 (listen(sck->m_endpoint, 5) != 0))
524 {
525 close(sck->m_endpoint);
526 sck->m_endpoint = -1;
527 sck->m_error = GSOCK_IOERR;
528 return GSOCK_IOERR;
529 }
530#endif
531 return GSOCK_NOERROR;
532}
533
534/* GSocket_WaitConnection:
535 * Waits for an incoming client connection. Returns a pointer to
536 * a GSocket object, or NULL if there was an error, in which case
537 * the last error field will be updated for the calling GSocket.
538 *
539 * Error codes (set in the calling GSocket)
540 * GSOCK_INVSOCK - the socket is not valid or not a server.
541 * GSOCK_TIMEDOUT - timeout, no incoming connections.
542 * GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
543 * GSOCK_MEMERR - couldn't allocate memory.
544 * GSOCK_IOERR - low-level error.
545 */
546GSocket *GSocket_WaitConnection(GSocket *socket)
547{
548 GSocket *connection = NULL ;
ee6b1d97
SC
549
550 assert(socket != NULL);
551
552 /* Reenable CONNECTION events */
553 socket->m_detected &= ~GSOCK_CONNECTION_FLAG;
554
555 /* If the socket has already been created, we exit immediately */
556 if (socket->m_endpoint == kOTInvalidEndpointRef || !socket->m_server)
557 {
558 socket->m_error = GSOCK_INVSOCK;
559 return NULL;
560 }
561
562 /* Create a GSocket object for the new connection */
563 connection = GSocket_new();
564
565 if (!connection)
566 {
567 socket->m_error = GSOCK_MEMERR;
568 return NULL;
569 }
570
571 /* Wait for a connection (with timeout) */
572 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
573 {
574 GSocket_destroy(connection);
575 /* socket->m_error set by _GSocket_Input_Timeout */
576 return NULL;
577 }
578
579// TODO
580#if 0
581 connection->m_endpoint = accept(socket->m_endpoint, &from, (SOCKLEN_T *) &fromlen);
582#endif
583
584 if (connection->m_endpoint == kOTInvalidEndpointRef )
585 {
586 if (errno == EWOULDBLOCK)
587 socket->m_error = GSOCK_WOULDBLOCK;
588 else
589 socket->m_error = GSOCK_IOERR;
590
591 GSocket_destroy(connection);
592 return NULL;
593 }
594
595 /* Initialize all fields */
596 connection->m_server = FALSE;
597 connection->m_stream = TRUE;
598 connection->m_oriented = TRUE;
599
600 /* Setup the peer address field */
601 connection->m_peer = GAddress_new();
602 if (!connection->m_peer)
603 {
604 GSocket_destroy(connection);
605 socket->m_error = GSOCK_MEMERR;
606 return NULL;
607 }
608 // TODO
609 #if 0
610 err = _GAddress_translate_from(connection->m_peer, &from, fromlen);
611 if (err != GSOCK_NOERROR)
612 {
613 GAddress_destroy(connection->m_peer);
614 GSocket_destroy(connection);
615 socket->m_error = err;
616 return NULL;
617 }
618
619 ioctl(connection->m_endpoint, FIONBIO, &arg);
620#endif
621 _GSocket_Enable_Events(connection);
622
623 return connection;
624}
625
626/* Datagram sockets */
627
628/* GSocket_SetNonOriented:
629 * Sets up this socket as a non-connection oriented (datagram) socket.
630 * Before using this function, the local address must have been set
631 * with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR
632 * on success, or one of the following otherwise.
633 *
634 * Error codes:
635 * GSOCK_INVSOCK - the socket is in use.
636 * GSOCK_INVADDR - the local address has not been set.
637 * GSOCK_IOERR - low-level error.
638 */
639GSocketError GSocket_SetNonOriented(GSocket *sck)
640{
ee6b1d97
SC
641 assert(sck != NULL);
642
643 if (sck->m_endpoint != kOTInvalidEndpointRef )
644 {
645 sck->m_error = GSOCK_INVSOCK;
646 return GSOCK_INVSOCK;
647 }
648
649 if (!sck->m_local)
650 {
651 sck->m_error = GSOCK_INVADDR;
652 return GSOCK_INVADDR;
653 }
654
655 /* Initialize all fields */
656 sck->m_stream = FALSE;
657 sck->m_server = FALSE;
658 sck->m_oriented = FALSE;
659
660 /* Create the socket */
661
662// TODO
663#if 0
664 sck->m_endpoint = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
665 socket_set_ref( sck->m_endpoint , (unsigned long) &gMacNetEvents , (unsigned long) sck ) ;
666#endif
667 if (sck->m_endpoint == kOTInvalidEndpointRef )
668 {
669 sck->m_error = GSOCK_IOERR;
670 return GSOCK_IOERR;
671 }
672
673// TODO
674#if 0
675 ioctl(sck->m_endpoint, FIONBIO, &arg);
676#endif
677 _GSocket_Enable_Events(sck);
678
679 /* Bind to the local address,
680 * and retrieve the actual address bound.
681 */
682// TODO
683#if 0
684 if ((bind(sck->m_endpoint, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
685 (getsockname(sck->m_endpoint,
686 sck->m_local->m_addr,
687 (SOCKLEN_T *) &sck->m_local->m_len) != 0))
688 {
689 close(sck->m_endpoint);
690 sck->m_endpoint = -1;
691 sck->m_error = GSOCK_IOERR;
692 return GSOCK_IOERR;
693 }
694#endif
695 return GSOCK_NOERROR;
696}
697
698/* Client specific parts */
699
700/* GSocket_Connect:
701 * For stream (connection oriented) sockets, GSocket_Connect() tries
702 * to establish a client connection to a server using the peer address
703 * as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the
704 * connection has been succesfully established, or one of the error
705 * codes listed below. Note that for nonblocking sockets, a return
706 * value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection
707 * request can be completed later; you should use GSocket_Select()
708 * to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the
709 * corresponding asynchronous events.
710 *
711 * For datagram (non connection oriented) sockets, GSocket_Connect()
712 * just sets the peer address established with GSocket_SetPeer() as
713 * default destination.
714 *
715 * Error codes:
716 * GSOCK_INVSOCK - the socket is in use or not valid.
717 * GSOCK_INVADDR - the peer address has not been established.
718 * GSOCK_TIMEDOUT - timeout, the connection failed.
719 * GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
720 * GSOCK_MEMERR - couldn't allocate memory.
721 * GSOCK_IOERR - low-level error.
722 */
723GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
724{
ee6b1d97
SC
725 InetAddress addr ;
726 TEndpointInfo info;
3340066a 727 OSStatus err = kOTNoError;
ee6b1d97
SC
728 TCall peer ;
729
730 assert(sck != NULL);
731
732 /* Enable CONNECTION events (needed for nonblocking connections) */
733 sck->m_detected &= ~GSOCK_CONNECTION_FLAG;
734
735 if (sck->m_endpoint != kOTInvalidEndpointRef )
736 {
737 sck->m_error = GSOCK_INVSOCK;
738 return GSOCK_INVSOCK;
739 }
740
741 if (!sck->m_peer)
742 {
743 sck->m_error = GSOCK_INVADDR;
744 return GSOCK_INVADDR;
745 }
746
747 /* Streamed or dgram socket? */
748 sck->m_stream = (stream == GSOCK_STREAMED);
749 sck->m_oriented = TRUE;
750 sck->m_server = FALSE;
751
752 /* Create the socket */
753#if TARGET_CARBON
754 sck->m_endpoint =
755 OTOpenEndpointInContext( OTCreateConfiguration( kTCPName) , 0 , &info , &err , NULL ) ;
756#else
757 sck->m_endpoint =
758 OTOpenEndpoint( OTCreateConfiguration( kTCPName) , 0 , &info , &err ) ;
759#endif
760 if ( sck->m_endpoint == kOTInvalidEndpointRef || err != kOTNoError )
761 {
762 sck->m_endpoint = kOTInvalidEndpointRef ;
763 sck->m_error = GSOCK_IOERR;
764 return GSOCK_IOERR;
765 }
766 err = OTBind( sck->m_endpoint , nil , nil ) ;
767 if ( err != kOTNoError )
768 {
769 return GSOCK_IOERR;
770 }
771 SetDefaultEndpointModes( sck->m_endpoint , sck ) ;
772// TODO
773#if 0
774 ioctl(sck->m_endpoint, FIONBIO, &arg);
775#endif
776 _GSocket_Enable_Events(sck);
777
778 _GAddress_translate_to( sck->m_peer , &addr ) ;
779 memset( &peer , 0 , sizeof( TCall ) ) ;
780 peer.addr.len = sizeof( InetAddress ) ;
781 peer.addr.buf = (unsigned char*) &addr ;
782 err = OTConnect( sck->m_endpoint , &peer , nil ) ;
783 if ( err != noErr )
784 {
785 /* If connect failed with EINPROGRESS and the GSocket object
786 * is in blocking mode, we select() for the specified timeout
787 * checking for writability to see if the connection request
788 * completes.
789 */
790
791 if ((err == kOTNoDataErr ) && (!sck->m_non_blocking))
792 {
793 if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT)
794 {
795 OTSndOrderlyDisconnect( sck->m_endpoint ) ;
796 sck->m_endpoint = kOTInvalidEndpointRef ;
797 /* sck->m_error is set in _GSocket_Output_Timeout */
798 return GSOCK_TIMEDOUT;
799 }
800 else
801 {
802/*
803 int error;
804 SOCKLEN_T len = sizeof(error);
805
806 getsockopt(sck->m_endpoint, SOL_SOCKET, SO_ERROR, (void*) &error, &len);
807
808 if (!error)
809*/
810 return GSOCK_NOERROR;
811 }
812 }
813
814 /* If connect failed with EINPROGRESS and the GSocket object
815 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
816 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
817 * this way if the connection completes, a GSOCK_CONNECTION
818 * event will be generated, if enabled.
819 */
820 if ((err == kOTNoDataErr) && (sck->m_non_blocking))
821 {
822 sck->m_error = GSOCK_WOULDBLOCK;
823 return GSOCK_WOULDBLOCK;
824 }
825
826 /* If connect failed with an error other than EINPROGRESS,
827 * then the call to GSocket_Connect has failed.
828 */
829 OTSndOrderlyDisconnect( sck->m_endpoint ) ;
830
831 sck->m_endpoint = kOTInvalidEndpointRef ;
832 sck->m_error = GSOCK_IOERR;
833 return GSOCK_IOERR;
834 }
835// OTInetEventHandler(sck, T_CONNECT , kOTNoError , NULL ) ;
836 return GSOCK_NOERROR;
837}
838
839/* Generic IO */
840
841/* Like recv(), send(), ... */
842int GSocket_Read(GSocket *socket, char *buffer, int size)
843{
844 int ret = 0 ;
845
846 assert(socket != NULL);
847
848 /* Reenable INPUT events */
849 socket->m_detected &= ~GSOCK_INPUT_FLAG;
850
851 if (socket->m_endpoint == kOTInvalidEndpointRef || socket->m_server)
852 {
853 socket->m_error = GSOCK_INVSOCK;
854 return -1;
855 }
856
857 /* If the socket is blocking, wait for data (with a timeout) */
858 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
859 return -1;
860
861 /* Read the data */
862 if (socket->m_stream)
863 ret = _GSocket_Recv_Stream(socket, buffer, size);
864 else
865 ret = _GSocket_Recv_Dgram(socket, buffer, size);
866
867 if (ret == -1)
868 {
869 if (errno == EWOULDBLOCK)
870 socket->m_error = GSOCK_WOULDBLOCK;
871 else
872 socket->m_error = GSOCK_IOERR;
873 }
874
875 return ret;
876}
877
878int GSocket_Write(GSocket *socket, const char *buffer, int size)
879{
880 int ret;
881
882 assert(socket != NULL);
883
884 if (socket->m_endpoint == kOTInvalidEndpointRef || socket->m_server)
885 {
886 socket->m_error = GSOCK_INVSOCK;
887 return -1;
888 }
889
890 /* If the socket is blocking, wait for writability (with a timeout) */
891 if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
892 return -1;
893
894 /* Write the data */
895 if (socket->m_stream)
896 ret = _GSocket_Send_Stream(socket, buffer, size);
897 else
898 ret = _GSocket_Send_Dgram(socket, buffer, size);
899
900 if (ret == -1)
901 {
902 if (errno == EWOULDBLOCK)
903 socket->m_error = GSOCK_WOULDBLOCK;
904 else
905 socket->m_error = GSOCK_IOERR;
906
907 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
908 * in MSW). Once the first OUTPUT event is received, users can assume
909 * that the socket is writable until a read operation fails. Only then
910 * will further OUTPUT events be posted.
911 */
912 socket->m_detected &= ~GSOCK_OUTPUT_FLAG;
913 return -1;
914 }
915
916 return ret;
917}
918
919/* GSocket_Select:
920 * Polls the socket to determine its status. This function will
921 * check for the events specified in the 'flags' parameter, and
922 * it will return a mask indicating which operations can be
923 * performed. This function won't block, regardless of the
924 * mode (blocking | nonblocking) of the socket.
925 */
926GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
927{
ee6b1d97
SC
928 assert(socket != NULL);
929 wxMacProcessNotifierEvents() ;
930 /*
931 state = OTGetEndpointState(socket->m_endpoint);
932
933 if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( socket->m_detected & GSOCK_INPUT_FLAG ) )
934 {
935 size_t sz = 0 ;
936 OTCountDataBytes( socket->m_endpoint , &sz ) ;
937 if ( state == T_INCON || sz > 0 )
938 {
939 socket->m_detected |= GSOCK_INPUT_FLAG ;
940 (socket->m_cbacks[GSOCK_INPUT])(socket, GSOCK_INPUT, socket->m_data[GSOCK_INPUT]);
941 }
942 }
943 if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( socket->m_detected & GSOCK_OUTPUT_FLAG ) )
944 {
945 if ( state == T_DATAXFER || state == T_INREL )
946 {
947 socket->m_detected |=GSOCK_OUTPUT_FLAG ;
948 (socket->m_cbacks[GSOCK_OUTPUT])(socket, GSOCK_OUTPUT, socket->m_data[GSOCK_OUTPUT]);
949 }
950 }
951 */
952 return ( flags & socket->m_detected ) ;
953}
954
955/* Flags */
956
957/* GSocket_SetNonBlocking:
958 * Sets the socket to non-blocking mode. All IO calls will return
959 * immediately.
960 */
961void GSocket_SetNonBlocking(GSocket *socket, int non_block)
962{
963 assert(socket != NULL);
964
965 socket->m_non_blocking = non_block;
966}
967
968/* GSocket_SetTimeout:
969 * Sets the timeout for blocking calls. Time is expressed in
970 * milliseconds.
971 */
972void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
973{
974 assert(socket != NULL);
975
79da3092
SC
976// this is usually set too high and we have not yet been able to detect a closed
977// stream, thus we leave the 10 sec timeout
978// socket->m_timeout = millisec;
ee6b1d97
SC
979}
980
981/* GSocket_GetError:
982 * Returns the last error occured for this socket. Note that successful
983 * operations do not clear this back to GSOCK_NOERROR, so use it only
984 * after an error.
985 */
986GSocketError GSocket_GetError(GSocket *socket)
987{
988 assert(socket != NULL);
989
990 return socket->m_error;
991}
992
993/* Callbacks */
994
995/* GSOCK_INPUT:
996 * There is data to be read in the input buffer. If, after a read
997 * operation, there is still data available, the callback function will
998 * be called again.
999 * GSOCK_OUTPUT:
1000 * The socket is available for writing. That is, the next write call
1001 * won't block. This event is generated only once, when the connection is
1002 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1003 * when the output buffer empties again. This means that the app should
1004 * assume that it can write since the first OUTPUT event, and no more
1005 * OUTPUT events will be generated unless an error occurs.
1006 * GSOCK_CONNECTION:
1007 * Connection succesfully established, for client sockets, or incoming
1008 * client connection, for server sockets. Wait for this event (also watch
1009 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1010 * GSOCK_LOST:
1011 * The connection is lost (or a connection request failed); this could
1012 * be due to a failure, or due to the peer closing it gracefully.
1013 */
1014
1015/* GSocket_SetCallback:
1016 * Enables the callbacks specified by 'flags'. Note that 'flags'
1017 * may be a combination of flags OR'ed toghether, so the same
1018 * callback function can be made to accept different events.
1019 * The callback function must have the following prototype:
1020 *
1021 * void function(GSocket *socket, GSocketEvent event, char *cdata)
1022 */
1023void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
1024 GSocketCallback callback, char *cdata)
1025{
1026 int count;
1027
1028 assert(socket != NULL);
1029
1030 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1031 {
1032 if ((flags & (1 << count)) != 0)
1033 {
1034 socket->m_cbacks[count] = callback;
1035 socket->m_data[count] = cdata;
1036 }
1037 }
1038}
1039
1040/* GSocket_UnsetCallback:
1041 * Disables all callbacks specified by 'flags', which may be a
1042 * combination of flags OR'ed toghether.
1043 */
1044void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
1045{
1046 int count;
1047
1048 assert(socket != NULL);
1049
1050 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1051 {
1052 if ((flags & (1 << count)) != 0)
1053 {
1054 socket->m_cbacks[count] = NULL;
1055 socket->m_data[count] = NULL;
1056 }
1057 }
1058}
1059
1060
1061#define CALL_CALLBACK(socket, event) { \
1062 _GSocket_Disable(socket, event); \
1063 if (socket->m_cbacks[event]) \
1064 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
1065}
1066
1067int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
1068{
1069 OTFlags flags ;
1070 OTResult res ;
5fde6fcc 1071 OTByteCount sz = 0 ;
ee6b1d97 1072
ee6b1d97 1073 OTCountDataBytes( socket->m_endpoint , &sz ) ;
79da3092
SC
1074 if ( size > sz )
1075 size = sz ;
ee6b1d97
SC
1076 res = OTRcv( socket->m_endpoint , buffer , size , &flags ) ;
1077 if ( res < 0 )
1078 {
1079 return -1 ;
1080 }
1081
1082 // we simulate another read event if there are still bytes
1083 if ( socket->m_takesEvents )
1084 {
5fde6fcc 1085 OTByteCount sz = 0 ;
ee6b1d97
SC
1086 OTCountDataBytes( socket->m_endpoint , &sz ) ;
1087 if ( sz > 0 )
1088 {
1089 socket->m_detected |= GSOCK_INPUT_FLAG ;
1090 (socket->m_cbacks[GSOCK_INPUT])(socket, GSOCK_INPUT, socket->m_data[GSOCK_INPUT]);
1091 }
1092 }
1093 return res ;
1094}
1095
1096int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
1097{
1098// TODO
1099 int ret = -1;
1100#if 0
1101 struct sockaddr from;
1102 SOCKLEN_T fromlen = sizeof(from);
1103 GSocketError err;
1104
1105 fromlen = sizeof(from);
1106
1107 ret = recvfrom(socket->m_endpoint, buffer, size, 0, &from, (SOCKLEN_T *) &fromlen);
1108
1109 if (ret == -1)
1110 return -1;
1111
1112 /* Translate a system address into a GSocket address */
1113 if (!socket->m_peer)
1114 {
1115 socket->m_peer = GAddress_new();
1116 if (!socket->m_peer)
1117 {
1118 socket->m_error = GSOCK_MEMERR;
1119 return -1;
1120 }
1121 }
1122 err = _GAddress_translate_from(socket->m_peer, &from, fromlen);
1123 if (err != GSOCK_NOERROR)
1124 {
1125 GAddress_destroy(socket->m_peer);
1126 socket->m_peer = NULL;
1127 socket->m_error = err;
1128 return -1;
1129 }
1130#endif
1131 return ret;
1132}
1133
1134int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
1135{
1136 OTFlags flags = 0 ;
1137 OTResult res ;
1138
1139 res = OTSnd( socket->m_endpoint , (void*) buffer , size , flags ) ;
1140 return res ;
1141}
1142
1143int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
1144{
1145 int ret = -1 ;
1146// TODO
1147#if 0
1148 struct sockaddr *addr;
1149 int len ;
1150 GSocketError err;
1151
1152 if (!socket->m_peer)
1153 {
1154 socket->m_error = GSOCK_INVADDR;
1155 return -1;
1156 }
1157
1158 err = _GAddress_translate_to(socket->m_peer, &addr, &len);
1159 if (err != GSOCK_NOERROR)
1160 {
1161 socket->m_error = err;
1162 return -1;
1163 }
1164
1165 ret = sendto(socket->m_endpoint, buffer, size, 0, addr, len);
1166
1167 /* Frees memory allocated from _GAddress_translate_to */
1168 free(addr);
1169#endif
1170 return ret;
1171}
1172
1173
1174/*
1175 * -------------------------------------------------------------------------
1176 * GAddress
1177 * -------------------------------------------------------------------------
1178 */
1179
1180/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY
1181 * or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it initalizes address
1182 * to be a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
1183 */
1184#define CHECK_ADDRESS(address, family, retval) \
1185{ \
1186 if (address->m_family == GSOCK_NOFAMILY) \
1187 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1188 return address->m_error; \
1189 if (address->m_family != GSOCK_##family) \
1190 { \
1191 address->m_error = GSOCK_INVADDR; \
1192 return retval; \
1193 } \
1194}
1195
1196GAddress *GAddress_new()
1197{
1198 GAddress *address;
1199
1200 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1201 return NULL;
1202
1203 address->m_family = GSOCK_NOFAMILY;
1204 address->m_host = INADDR_NONE ;
1205 address->m_port = 0 ;
1206
1207 return address;
1208}
1209
1210GAddress *GAddress_copy(GAddress *address)
1211{
1212 GAddress *addr2;
1213
1214 assert(address != NULL);
1215
1216 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1217 return NULL;
1218
1219 memcpy(addr2, address, sizeof(GAddress));
1220 return addr2;
1221}
1222
1223void GAddress_destroy(GAddress *address)
1224{
1225 assert(address != NULL);
1226
1227 free(address);
1228}
1229
1230void GAddress_SetFamily(GAddress *address, GAddressType type)
1231{
1232 assert(address != NULL);
1233
1234 address->m_family = type;
1235}
1236
1237GAddressType GAddress_GetFamily(GAddress *address)
1238{
1239 assert(address != NULL);
1240
1241 return address->m_family;
1242}
1243
1244GSocketError _GAddress_translate_from(GAddress *address,
1245 InetAddress *addr)
1246{
1247 switch (addr->fAddressType)
1248 {
1249 case AF_INET:
1250 address->m_family = GSOCK_INET;
1251 break;
1252#ifdef AF_INET6
1253 case AF_INET6:
1254 address->m_family = GSOCK_INET6;
1255 break;
1256#endif
1257 default:
1258 {
1259 address->m_error = GSOCK_INVOP;
1260 return GSOCK_INVOP;
1261 }
1262 }
1263 address->m_host = addr->fHost ;
1264 address->m_port = addr->fPort ;
1265 return GSOCK_NOERROR;
1266}
1267
1268GSocketError _GAddress_translate_to(GAddress *address,
1269 InetAddress *addr)
1270{
79da3092
SC
1271 if ( GSocket_Verify_Inited() == FALSE )
1272 return GSOCK_IOERR ;
ee6b1d97
SC
1273 memset(addr, 0 , sizeof(struct InetAddress));
1274 OTInitInetAddress( addr , address->m_port , address->m_host ) ;
1275 return GSOCK_NOERROR;
1276}
1277
1278/*
1279 * -------------------------------------------------------------------------
1280 * Internet address family
1281 * -------------------------------------------------------------------------
1282 */
1283
1284GSocketError _GAddress_Init_INET(GAddress *address)
1285{
1286 address->m_family = GSOCK_INET;
1287 address->m_host = kOTAnyInetAddress ;
1288
1289 return GSOCK_NOERROR;
1290}
1291
1292GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1293{
1294 InetHostInfo hinfo ;
1295 OSStatus ret ;
1296
79da3092
SC
1297 if ( GSocket_Verify_Inited() == FALSE )
1298 return GSOCK_IOERR ;
1299
ee6b1d97
SC
1300 assert(address != NULL);
1301
1302 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1303 ret = OTInetStringToAddress( gInetSvcRef , (char*) hostname , &hinfo ) ;
1304 if ( ret != kOTNoError )
1305 {
1306 address->m_host = INADDR_NONE ;
1307 address->m_error = GSOCK_NOHOST;
1308 return GSOCK_NOHOST;
1309 }
1310 address->m_host = hinfo.addrs[0] ;
1311 return GSOCK_NOERROR;
1312}
1313
1314GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1315{
1316 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1317}
1318
1319GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1320 unsigned long hostaddr)
1321{
ee6b1d97
SC
1322 assert(address != NULL);
1323
1324 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1325
1326 address->m_host = hostaddr ;
1327
1328 return GSOCK_NOERROR;
1329}
1330
1331struct service_entry
1332{
1333 char * name ;
1334 unsigned short port ;
1335 char * protocol ;
1336} ;
1337typedef struct service_entry service_entry ;
1338
1339service_entry gServices[] =
1340{
1341 { "http" , 80 , "tcp" }
1342} ;
1343
1344GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1345 const char *protocol)
1346{
ee6b1d97
SC
1347 int i ;
1348
1349 assert(address != NULL);
1350 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1351
1352 if (!port)
1353 {
1354 address->m_error = GSOCK_INVPORT;
1355 return GSOCK_INVPORT;
1356 }
1357 for ( i = 0 ; i < sizeof( gServices) / sizeof( service_entry ) ; ++i )
1358 {
1359 if ( strcmp( port , gServices[i].name ) == 0 )
1360 {
1361 if ( protocol == NULL || strcmp( protocol , gServices[i].protocol ) )
1362 {
1363 address->m_port = gServices[i].port ;
1364 return GSOCK_NOERROR;
1365 }
1366 }
1367 }
1368
1369 if (isdigit(port[0]))
1370 {
1371 address->m_port = atoi(port);
1372 return GSOCK_NOERROR;
1373 }
1374
1375 address->m_error = GSOCK_INVPORT;
1376 return GSOCK_INVPORT;
1377}
1378
1379GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1380{
ee6b1d97
SC
1381 assert(address != NULL);
1382 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1383 address->m_port = port ;
1384
1385 return GSOCK_NOERROR;
1386}
1387
1388GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1389{
1390 InetDomainName name ;
79da3092
SC
1391 if ( GSocket_Verify_Inited() == FALSE )
1392 return GSOCK_IOERR ;
ee6b1d97
SC
1393
1394 assert(address != NULL);
1395 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1396
5fde6fcc 1397 OTInetAddressToName( gInetSvcRef , address->m_host , name ) ;
ee6b1d97
SC
1398 strncpy( hostname , name , sbuf ) ;
1399 return GSOCK_NOERROR;
1400}
1401
1402unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1403{
1404 assert(address != NULL);
1405 CHECK_ADDRESS(address, INET, 0);
1406
1407 return address->m_host;
1408}
1409
1410unsigned short GAddress_INET_GetPort(GAddress *address)
1411{
1412 assert(address != NULL);
1413 CHECK_ADDRESS(address, INET, 0);
1414
1415 return address->m_port;
1416}
1417
1418void _GSocket_Enable_Events(GSocket *socket)
1419{
1420 if ( socket->m_takesEvents )
1421 return ;
1422
1423 {
1424 OTResult state ;
1425 socket->m_takesEvents = TRUE ;
1426 state = OTGetEndpointState(socket->m_endpoint);
1427
1428 {
5fde6fcc 1429 OTByteCount sz = 0 ;
ee6b1d97
SC
1430 OTCountDataBytes( socket->m_endpoint , &sz ) ;
1431 if ( state == T_INCON || sz > 0 )
1432 {
1433 socket->m_detected |= GSOCK_INPUT_FLAG ;
1434 (socket->m_cbacks[GSOCK_INPUT])(socket, GSOCK_INPUT, socket->m_data[GSOCK_INPUT]);
1435 }
1436 }
1437 {
1438 if ( state == T_DATAXFER || state == T_INREL )
1439 {
1440 socket->m_detected |=GSOCK_OUTPUT_FLAG ;
1441 (socket->m_cbacks[GSOCK_OUTPUT])(socket, GSOCK_OUTPUT, socket->m_data[GSOCK_OUTPUT]);
1442 }
1443 }
1444 }
1445}
1446
1447void _GSocket_Disable_Events(GSocket *socket)
1448{
1449 socket->m_takesEvents = FALSE ;
1450}
1451
1452/* _GSocket_Input_Timeout:
1453 * For blocking sockets, wait until data is available or
1454 * until timeout ellapses.
1455 */
1456GSocketError _GSocket_Input_Timeout(GSocket *socket)
1457{
1458 if ( !socket->m_non_blocking )
1459 {
1460 UnsignedWide now , start ;
1461 short formerTakesEvents = socket->m_takesEvents ;
1462 Microseconds(&start);
1463 now = start ;
1464 socket->m_takesEvents = FALSE ;
1465
1466 while( (now.hi * 4294967296.0 + now.lo) - (start.hi * 4294967296.0 + start.lo) < socket->m_timeout * 1000.0 )
1467 {
1468 OTResult state ;
5fde6fcc 1469 OTByteCount sz = 0 ;
62e83765 1470 state = OTGetEndpointState(socket->m_endpoint);
ee6b1d97
SC
1471
1472 OTCountDataBytes( socket->m_endpoint , &sz ) ;
1473 if ( state == T_INCON || sz > 0 )
1474 {
1475 socket->m_takesEvents = formerTakesEvents ;
1476 return GSOCK_NOERROR;
1477 }
1478 Microseconds(&now);
1479 }
1480 socket->m_takesEvents = formerTakesEvents ;
1481 socket->m_error = GSOCK_TIMEDOUT;
1482 return GSOCK_TIMEDOUT;
1483 }
1484 return GSOCK_NOERROR;
1485}
1486
1487/* _GSocket_Output_Timeout:
1488 * For blocking sockets, wait until data can be sent without
1489 * blocking or until timeout ellapses.
1490 */
1491GSocketError _GSocket_Output_Timeout(GSocket *socket)
1492{
1493 if ( !socket->m_non_blocking )
1494 {
1495 UnsignedWide now , start ;
1496 short formerTakesEvents = socket->m_takesEvents ;
1497 Microseconds(&start);
1498 now = start ;
1499 socket->m_takesEvents = FALSE ;
1500
1501 while( (now.hi * 4294967296.0 + now.lo) - (start.hi * 4294967296.0 + start.lo) < socket->m_timeout * 1000.0 )
1502 {
1503 OTResult state ;
1504 state = OTGetEndpointState(socket->m_endpoint);
1505
1506 if ( state == T_DATAXFER || state == T_INREL )
1507 {
1508 socket->m_takesEvents = formerTakesEvents ;
1509 return GSOCK_NOERROR;
1510 }
1511 Microseconds(&now);
1512 }
1513 socket->m_takesEvents = formerTakesEvents ;
1514 socket->m_error = GSOCK_TIMEDOUT;
1515 return GSOCK_TIMEDOUT;
1516 }
1517 return GSOCK_NOERROR;
1518}
1519
1520/* GSOCK_INPUT:
1521 * There is data to be read in the input buffer. If, after a read
1522 * operation, there is still data available, the callback function will
1523 * be called again.
1524 * GSOCK_OUTPUT:
1525 * The socket is available for writing. That is, the next write call
1526 * won't block. This event is generated only once, when the connection is
1527 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1528 * when the output buffer empties again. This means that the app should
1529 * assume that it can write since the first OUTPUT event, and no more
1530 * OUTPUT events will be generated unless an error occurs.
1531 * GSOCK_CONNECTION:
1532 * Connection succesfully established, for client sockets, or incoming
1533 * client connection, for server sockets. Wait for this event (also watch
1534 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1535 * GSOCK_LOST:
1536 * The connection is lost (or a connection request failed); this could
1537 * be due to a failure, or due to the peer closing it gracefully.
1538 */
1539
1540void _GSocket_Internal_Proc(unsigned long e , void* d )
1541{
1542
1543 GSocket * socket = (GSocket*) d ;
1544 OTEventCode ev = (OTEventCode) e ;
1545 GSocketEvent event;
1546 GSocketEvent event2;
1547 GSocketCallback cback;
1548 char *data;
1549 GSocketCallback cback2;
1550 char *data2;
1551
1552 if ( !socket )
1553 return ;
1554 event = GSOCK_MAX_EVENT ;
1555 event2 = GSOCK_MAX_EVENT ;
1556 cback = NULL;
1557 data = NULL;
1558 cback2 = NULL;
1559 data2 = NULL;
1560
1561 /* Check that the socket still exists (it has not been
1562 * destroyed) and for safety, check that the m_endpoint field
1563 * is what we expect it to be.
1564 */
1565 if ((socket != NULL) && (socket->m_takesEvents))
1566 {
1567 switch (ev)
1568 {
1569 case T_LISTEN :
1570 event = GSOCK_CONNECTION ;
1571 break ;
1572 case T_CONNECT :
1573 event = GSOCK_CONNECTION ;
1574 event2 = GSOCK_OUTPUT ;
1575 {
1576 TCall retCall;
1577
1578 retCall.addr.buf = NULL;
1579 retCall.addr.maxlen = 0;
1580 retCall.opt.buf = NULL;
1581 retCall.opt.maxlen = 0;
1582 retCall.udata.buf = NULL;
1583 retCall.udata.maxlen= 0;
1584 OTRcvConnect( socket->m_endpoint , &retCall ) ;
1585 }
1586 break ;
1587 case T_DISCONNECT :
1588 event = GSOCK_LOST ;
1589 break ;
1590 case T_GODATA :
1591 case T_GOEXDATA :
1592 event = GSOCK_OUTPUT ;
1593 break ;
1594 case T_DATA :
1595 event = GSOCK_INPUT ;
1596 break ;
1597 case T_EXDATA :
1598 event = GSOCK_INPUT ;
1599 break ;
1600 }
1601 if (event != GSOCK_MAX_EVENT)
1602 {
1603 cback = socket->m_cbacks[event];
1604 data = socket->m_data[event];
1605
1606 if (event == GSOCK_LOST)
1607 socket->m_detected = GSOCK_LOST_FLAG;
1608 else
1609 socket->m_detected |= (1 << event);
1610 }
1611 if (event2 != GSOCK_MAX_EVENT)
1612 {
1613 cback2 = socket->m_cbacks[event2];
1614 data2 = socket->m_data[event2];
1615
1616 if (event2 == GSOCK_LOST)
1617 socket->m_detected = GSOCK_LOST_FLAG;
1618 else
1619 socket->m_detected |= (1 << event2);
1620 }
1621 }
1622
1623 /* OK, we can now leave the critical section because we have
1624 * already obtained the callback address (we make no further
1625 * accesses to socket->whatever). However, the app should
1626 * be prepared to handle events from a socket that has just
1627 * been closed!
1628 */
1629
1630 if (cback != NULL)
1631 (cback)(socket, event, data);
1632 if (cback2 != NULL)
1633 (cback2)(socket, event2, data2);
1634
1635}
1636
03e11df5
GD
1637/* Hack added for Mac OS X */
1638GSocketError GAddress_UNIX_GetPath(GAddress *addr, char *path, size_t buf)
1639{
d84afea9 1640 return GSOCK_INVADDR;
03e11df5
GD
1641}
1642
1643GSocketError GAddress_UNIX_SetPath(GAddress *addr, const char *path)
1644{
d84afea9 1645 return GSOCK_INVADDR;
03e11df5
GD
1646}
1647
ee6b1d97 1648#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */