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