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