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