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