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