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