]> git.saurik.com Git - wxWidgets.git/blame - src/mac/gsocket.c
applied correction from Marc Newsam in calculations of linesize
[wxWidgets.git] / src / mac / gsocket.c
CommitLineData
ee6b1d97
SC
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Authors: Guilhem Lavaux,
5 * Guillermo Rodriguez Garcia <guille@iies.es> (maintainer)
6 * Stefan CSomor
7 * Purpose: GSocket main mac file
8 * CVSID: $Id$
9 * -------------------------------------------------------------------------
10 */
11
12/*
13 * PLEASE don't put C++ comments here - this is a C source file.
14 */
15
16#ifndef __GSOCKET_STANDALONE__
17#include "wx/setup.h"
18#endif
19
20#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
21
03e11df5 22#ifdef __UNIX__
5fde6fcc 23 #include <CoreServices/CoreServices.h>
03e11df5
GD
24
25 #ifndef FALSE
26 #define FALSE 0
27 #endif
28 #ifndef TRUE
29 #define TRUE 1
30 #endif
31#else
5fde6fcc 32 #define OTUNIXERRORS 1
03e11df5
GD
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
ee6b1d97
SC
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>
ee6b1d97
SC
49#include <utime.h>
50
51/*
52 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
53 * on all unices. INADDR_BROADCAST should be fine to indicate an error.
54 */
55#ifndef INADDR_BROADCAST
56#define INADDR_BROADCAST 0xFFFFFFFFUL
57#endif
58#ifndef INADDR_NONE
59#define INADDR_NONE INADDR_BROADCAST
60#endif
61#ifndef INADDR_ANY
62#define INADDR_ANY 0x0UL
63#endif
64#ifndef __GSOCKET_STANDALONE__
65
66#include "wx/mac/macnotfy.h"
67#include "wx/mac/gsockmac.h"
68#include "wx/gsocket.h"
69
70#else
71
72#include "gsockmac.h"
73#include "gsocket.h"
74
75#endif /* __GSOCKET_STANDALONE__ */
76
77void wxCYield() ;
78#ifdef __WXDEBUG__
79#define qDebug 1
80#define qDebug2 1
81extern pascal void OTDebugStr(const char* str);
82#endif
03e11df5
GD
83#ifndef __UNIX__
84 #include <OTDebug.h>
85#endif
ee6b1d97
SC
86InetSvcRef gInetSvcRef = 0 ;
87
88
89OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode);
90
91/* Input: ep - endpointref on which to negotiate the option
92 enableReuseIPMode - desired option setting - true/false
93 Return: kOTNoError indicates that the option was successfully negotiated
94 OSStatus is an error if < 0, otherwise, the status field is
95 returned and is > 0.
96
97 IMPORTANT NOTE: The endpoint is assumed to be in synchronous more, otherwise
98 this code will not function as desired
99*/
100
101
102OSStatus DoNegotiateIPReuseAddrOption(EndpointRef ep, Boolean enableReuseIPMode)
103
104{
105 UInt8 buf[kOTFourByteOptionSize]; // define buffer for fourByte Option size
106 TOption* opt; // option ptr to make items easier to access
107 TOptMgmt req;
108 TOptMgmt ret;
109 OSStatus err;
110
111 if (!OTIsSynchronous(ep))
112 {
113 return (-1);
114 }
115 opt = (TOption*)buf; // set option ptr to buffer
116 req.opt.buf = buf;
117 req.opt.len = sizeof(buf);
118 req.flags = T_NEGOTIATE; // negotiate for option
119
120 ret.opt.buf = buf;
121 ret.opt.maxlen = kOTFourByteOptionSize;
122
123 opt->level = INET_IP; // dealing with an IP Level function
5fde6fcc
GD
124#ifdef __UNIX__
125 opt->name = kIP_REUSEADDR;
126#else
ee6b1d97 127 opt->name = IP_REUSEADDR;
5fde6fcc 128#endif
ee6b1d97
SC
129 opt->len = kOTFourByteOptionSize;
130 opt->status = 0;
131 *(UInt32*)opt->value = enableReuseIPMode; // set the desired option level, true or false
132
133 err = OTOptionManagement(ep, &req, &ret);
134
135 // if no error then return the option status value
136 if (err == kOTNoError)
137 {
138 if (opt->status != T_SUCCESS)
139 err = opt->status;
140 else
141 err = kOTNoError;
142 }
143
144 return err;
145}
146
147
148pascal void OTInetEventHandler(void*s, OTEventCode event, OTResult, void *cookie) ;
149pascal void OTInetEventHandler(void*s, OTEventCode event, OTResult result, void *cookie)
150{
151 int wakeUp = true ;
152 GSocket* sock = (GSocket*) s ;
153
154 if ( event == kOTSyncIdleEvent )
155 {
156 YieldToAnyThread() ;
157 return ;
158 }
159
160 if ( s )
161 {
162 wxMacAddEvent( sock->m_mac_events , _GSocket_Internal_Proc , event , s , wakeUp ) ;
163 }
164
165 return;
166}
167
168static void SetDefaultEndpointModes(EndpointRef ep , void *data )
169 // This routine sets the supplied endpoint into the default
170 // mode used in this application. The specifics are:
171 // blocking, synchronous, and using synch idle events with
172 // the standard YieldingNotifier.
173{
174 OSStatus junk = kOTNoError ;
175 OTAssert ("SetDefaultEndpointModes:invalid ref", ep != kOTInvalidEndpointRef ) ;
176 junk = OTSetAsynchronous(ep);
177 OTAssert("SetDefaultEndpointModes: Could not set asynchronous", junk == noErr);
178/*
179 junk = OTSetBlocking(ep);
180 OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr);
181 junk = OTSetSynchronous(ep);
182 OTAssert("SetDefaultEndpointModes: Could not set synchronous", junk == noErr);
183 junk = OTSetBlocking(ep);
184 OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr);
185*/
186 junk = OTInstallNotifier(ep, OTInetEventHandler, data);
187 OTAssert("SetDefaultEndpointModes: Could not install notifier", junk == noErr);
188/*
189 junk = OTUseSyncIdleEvents(ep, true);
190 OTAssert("SetDefaultEndpointModes: Could not use sync idle events", junk == noErr);
191*/
192}
193
194/* Global initialisers */
195
196int GSocket_Init()
197{
198 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
213void 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
226GSocket *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
255void 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 */
279void 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 */
326GSocketError 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
352GSocketError 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
371GAddress *GSocket_GetLocal(GSocket *socket)
372{
373 GAddress *address = NULL ;
ee6b1d97
SC
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
422GAddress *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 */
445GSocketError 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 */
516GSocket *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 */
612GSocketError 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 */
698GSocketError 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(), ... */
820int 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
856int 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 */
904GSocketEventFlags 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 */
940void 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 */
951void 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 */
963GSocketError 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 */
1000void 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 */
1021void 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
1044int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
1045{
1046 OTFlags flags ;
1047 OTResult res ;
5fde6fcc 1048 OTByteCount sz = 0 ;
ee6b1d97 1049
ee6b1d97
SC
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 {
5fde6fcc 1060 OTByteCount sz = 0 ;
ee6b1d97
SC
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
1071int _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
1109int _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
1118int _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
1171GAddress *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
1185GAddress *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
1198void GAddress_destroy(GAddress *address)
1199{
1200 assert(address != NULL);
1201
1202 free(address);
1203}
1204
1205void GAddress_SetFamily(GAddress *address, GAddressType type)
1206{
1207 assert(address != NULL);
1208
1209 address->m_family = type;
1210}
1211
1212GAddressType GAddress_GetFamily(GAddress *address)
1213{
1214 assert(address != NULL);
1215
1216 return address->m_family;
1217}
1218
1219GSocketError _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
1243GSocketError _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
1257GSocketError _GAddress_Init_INET(GAddress *address)
1258{
1259 address->m_family = GSOCK_INET;
1260 address->m_host = kOTAnyInetAddress ;
1261
1262 return GSOCK_NOERROR;
1263}
1264
1265GSocketError 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
1284GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1285{
1286 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1287}
1288
1289GSocketError 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
1303struct service_entry
1304{
1305 char * name ;
1306 unsigned short port ;
1307 char * protocol ;
1308} ;
1309typedef struct service_entry service_entry ;
1310
1311service_entry gServices[] =
1312{
1313 { "http" , 80 , "tcp" }
1314} ;
1315
1316GSocketError 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
1352GSocketError 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
1363GSocketError 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
5fde6fcc 1370 OTInetAddressToName( gInetSvcRef , address->m_host , name ) ;
ee6b1d97
SC
1371 strncpy( hostname , name , sbuf ) ;
1372 return GSOCK_NOERROR;
1373}
1374
1375unsigned 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
1383unsigned 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
1391void _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 {
5fde6fcc 1402 OTByteCount sz = 0 ;
ee6b1d97
SC
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
1420void _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 */
1429GSocketError _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 ;
5fde6fcc 1442 OTByteCount sz = 0 ;
ee6b1d97
SC
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 */
1464GSocketError _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
1513void _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
03e11df5
GD
1610/* Hack added for Mac OS X */
1611GSocketError GAddress_UNIX_GetPath(GAddress *addr, char *path, size_t buf)
1612{
1613}
1614
1615GSocketError GAddress_UNIX_SetPath(GAddress *addr, const char *path)
1616{
1617}
1618
ee6b1d97 1619#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */