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