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