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