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