]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/gsocket.c
Moved the cleanup code to an EVT_WINDOW_DESTROY handler.
[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
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{
476 int type;
477 int arg = 1;
478
479 assert(sck != NULL);
480
481 /* must not be in use */
482 if (sck->m_endpoint != kOTInvalidEndpointRef )
483 {
484 sck->m_error = GSOCK_INVSOCK;
485 return GSOCK_INVSOCK;
486 }
487
488 /* the local addr must have been set */
489 if (!sck->m_local)
490 {
491 sck->m_error = GSOCK_INVADDR;
492 return GSOCK_INVADDR;
493 }
494
495 /* Initialize all fields */
496 sck->m_stream = TRUE;
497 sck->m_server = TRUE;
498 sck->m_oriented = TRUE;
499
500// TODO
501#if 0
502 /* Create the socket */
503 sck->m_endpoint = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
504 socket_set_ref( sck->m_endpoint , (unsigned long) &gMacNetEvents , (unsigned long) sck ) ;
505 if (sck->m_endpoint == kOTInvalidEndpointRef)
506 {
507 sck->m_error = GSOCK_IOERR;
508 return GSOCK_IOERR;
509 }
510
511 ioctl(sck->m_endpoint, FIONBIO, &arg);
512 _GSocket_Enable_Events(sck);
513
514 /* Bind to the local address,
515 * retrieve the actual address bound,
516 * and listen up to 5 connections.
517 */
518 if ((bind(sck->m_endpoint, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
519 (getsockname(sck->m_endpoint,
520 sck->m_local->m_addr,
521 (SOCKLEN_T *) &sck->m_local->m_len) != 0) ||
522 (listen(sck->m_endpoint, 5) != 0))
523 {
524 close(sck->m_endpoint);
525 sck->m_endpoint = -1;
526 sck->m_error = GSOCK_IOERR;
527 return GSOCK_IOERR;
528 }
529#endif
530 return GSOCK_NOERROR;
531}
532
533/* GSocket_WaitConnection:
534 * Waits for an incoming client connection. Returns a pointer to
535 * a GSocket object, or NULL if there was an error, in which case
536 * the last error field will be updated for the calling GSocket.
537 *
538 * Error codes (set in the calling GSocket)
539 * GSOCK_INVSOCK - the socket is not valid or not a server.
540 * GSOCK_TIMEDOUT - timeout, no incoming connections.
541 * GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
542 * GSOCK_MEMERR - couldn't allocate memory.
543 * GSOCK_IOERR - low-level error.
544 */
545GSocket *GSocket_WaitConnection(GSocket *socket)
546{
547 GSocket *connection = NULL ;
548 GSocketError err;
549
550 int arg = 1;
551
552 assert(socket != NULL);
553
554 /* Reenable CONNECTION events */
555 socket->m_detected &= ~GSOCK_CONNECTION_FLAG;
556
557 /* If the socket has already been created, we exit immediately */
558 if (socket->m_endpoint == kOTInvalidEndpointRef || !socket->m_server)
559 {
560 socket->m_error = GSOCK_INVSOCK;
561 return NULL;
562 }
563
564 /* Create a GSocket object for the new connection */
565 connection = GSocket_new();
566
567 if (!connection)
568 {
569 socket->m_error = GSOCK_MEMERR;
570 return NULL;
571 }
572
573 /* Wait for a connection (with timeout) */
574 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
575 {
576 GSocket_destroy(connection);
577 /* socket->m_error set by _GSocket_Input_Timeout */
578 return NULL;
579 }
580
581// TODO
582#if 0
583 connection->m_endpoint = accept(socket->m_endpoint, &from, (SOCKLEN_T *) &fromlen);
584#endif
585
586 if (connection->m_endpoint == kOTInvalidEndpointRef )
587 {
588 if (errno == EWOULDBLOCK)
589 socket->m_error = GSOCK_WOULDBLOCK;
590 else
591 socket->m_error = GSOCK_IOERR;
592
593 GSocket_destroy(connection);
594 return NULL;
595 }
596
597 /* Initialize all fields */
598 connection->m_server = FALSE;
599 connection->m_stream = TRUE;
600 connection->m_oriented = TRUE;
601
602 /* Setup the peer address field */
603 connection->m_peer = GAddress_new();
604 if (!connection->m_peer)
605 {
606 GSocket_destroy(connection);
607 socket->m_error = GSOCK_MEMERR;
608 return NULL;
609 }
610 // TODO
611 #if 0
612 err = _GAddress_translate_from(connection->m_peer, &from, fromlen);
613 if (err != GSOCK_NOERROR)
614 {
615 GAddress_destroy(connection->m_peer);
616 GSocket_destroy(connection);
617 socket->m_error = err;
618 return NULL;
619 }
620
621 ioctl(connection->m_endpoint, FIONBIO, &arg);
622#endif
623 _GSocket_Enable_Events(connection);
624
625 return connection;
626}
627
628/* Datagram sockets */
629
630/* GSocket_SetNonOriented:
631 * Sets up this socket as a non-connection oriented (datagram) socket.
632 * Before using this function, the local address must have been set
633 * with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR
634 * on success, or one of the following otherwise.
635 *
636 * Error codes:
637 * GSOCK_INVSOCK - the socket is in use.
638 * GSOCK_INVADDR - the local address has not been set.
639 * GSOCK_IOERR - low-level error.
640 */
641GSocketError GSocket_SetNonOriented(GSocket *sck)
642{
643 int arg = 1;
644
645 assert(sck != NULL);
646
647 if (sck->m_endpoint != kOTInvalidEndpointRef )
648 {
649 sck->m_error = GSOCK_INVSOCK;
650 return GSOCK_INVSOCK;
651 }
652
653 if (!sck->m_local)
654 {
655 sck->m_error = GSOCK_INVADDR;
656 return GSOCK_INVADDR;
657 }
658
659 /* Initialize all fields */
660 sck->m_stream = FALSE;
661 sck->m_server = FALSE;
662 sck->m_oriented = FALSE;
663
664 /* Create the socket */
665
666// TODO
667#if 0
668 sck->m_endpoint = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
669 socket_set_ref( sck->m_endpoint , (unsigned long) &gMacNetEvents , (unsigned long) sck ) ;
670#endif
671 if (sck->m_endpoint == kOTInvalidEndpointRef )
672 {
673 sck->m_error = GSOCK_IOERR;
674 return GSOCK_IOERR;
675 }
676
677// TODO
678#if 0
679 ioctl(sck->m_endpoint, FIONBIO, &arg);
680#endif
681 _GSocket_Enable_Events(sck);
682
683 /* Bind to the local address,
684 * and retrieve the actual address bound.
685 */
686// TODO
687#if 0
688 if ((bind(sck->m_endpoint, sck->m_local->m_addr, sck->m_local->m_len) != 0) ||
689 (getsockname(sck->m_endpoint,
690 sck->m_local->m_addr,
691 (SOCKLEN_T *) &sck->m_local->m_len) != 0))
692 {
693 close(sck->m_endpoint);
694 sck->m_endpoint = -1;
695 sck->m_error = GSOCK_IOERR;
696 return GSOCK_IOERR;
697 }
698#endif
699 return GSOCK_NOERROR;
700}
701
702/* Client specific parts */
703
704/* GSocket_Connect:
705 * For stream (connection oriented) sockets, GSocket_Connect() tries
706 * to establish a client connection to a server using the peer address
707 * as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the
708 * connection has been succesfully established, or one of the error
709 * codes listed below. Note that for nonblocking sockets, a return
710 * value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection
711 * request can be completed later; you should use GSocket_Select()
712 * to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the
713 * corresponding asynchronous events.
714 *
715 * For datagram (non connection oriented) sockets, GSocket_Connect()
716 * just sets the peer address established with GSocket_SetPeer() as
717 * default destination.
718 *
719 * Error codes:
720 * GSOCK_INVSOCK - the socket is in use or not valid.
721 * GSOCK_INVADDR - the peer address has not been established.
722 * GSOCK_TIMEDOUT - timeout, the connection failed.
723 * GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
724 * GSOCK_MEMERR - couldn't allocate memory.
725 * GSOCK_IOERR - low-level error.
726 */
727GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
728{
729 int ret;
730 int arg = 1;
731 InetAddress addr ;
732 TEndpointInfo info;
733 OTFlags flags = 0;
734 OSStatus err = kOTNoError;
735 TCall peer ;
736
737 assert(sck != NULL);
738
739 /* Enable CONNECTION events (needed for nonblocking connections) */
740 sck->m_detected &= ~GSOCK_CONNECTION_FLAG;
741
742 if (sck->m_endpoint != kOTInvalidEndpointRef )
743 {
744 sck->m_error = GSOCK_INVSOCK;
745 return GSOCK_INVSOCK;
746 }
747
748 if (!sck->m_peer)
749 {
750 sck->m_error = GSOCK_INVADDR;
751 return GSOCK_INVADDR;
752 }
753
754 /* Streamed or dgram socket? */
755 sck->m_stream = (stream == GSOCK_STREAMED);
756 sck->m_oriented = TRUE;
757 sck->m_server = FALSE;
758
759 /* Create the socket */
760#if TARGET_CARBON
761 sck->m_endpoint =
762 OTOpenEndpointInContext( OTCreateConfiguration( kTCPName) , 0 , &info , &err , NULL ) ;
763#else
764 sck->m_endpoint =
765 OTOpenEndpoint( OTCreateConfiguration( kTCPName) , 0 , &info , &err ) ;
766#endif
767 if ( sck->m_endpoint == kOTInvalidEndpointRef || err != kOTNoError )
768 {
769 sck->m_endpoint = kOTInvalidEndpointRef ;
770 sck->m_error = GSOCK_IOERR;
771 return GSOCK_IOERR;
772 }
773 err = OTBind( sck->m_endpoint , nil , nil ) ;
774 if ( err != kOTNoError )
775 {
776 return GSOCK_IOERR;
777 }
778 SetDefaultEndpointModes( sck->m_endpoint , sck ) ;
779// TODO
780#if 0
781 ioctl(sck->m_endpoint, FIONBIO, &arg);
782#endif
783 _GSocket_Enable_Events(sck);
784
785 _GAddress_translate_to( sck->m_peer , &addr ) ;
786 memset( &peer , 0 , sizeof( TCall ) ) ;
787 peer.addr.len = sizeof( InetAddress ) ;
788 peer.addr.buf = (unsigned char*) &addr ;
789 err = OTConnect( sck->m_endpoint , &peer , nil ) ;
790 if ( err != noErr )
791 {
792 /* If connect failed with EINPROGRESS and the GSocket object
793 * is in blocking mode, we select() for the specified timeout
794 * checking for writability to see if the connection request
795 * completes.
796 */
797
798 if ((err == kOTNoDataErr ) && (!sck->m_non_blocking))
799 {
800 if (_GSocket_Output_Timeout(sck) == GSOCK_TIMEDOUT)
801 {
802 OTSndOrderlyDisconnect( sck->m_endpoint ) ;
803 sck->m_endpoint = kOTInvalidEndpointRef ;
804 /* sck->m_error is set in _GSocket_Output_Timeout */
805 return GSOCK_TIMEDOUT;
806 }
807 else
808 {
809/*
810 int error;
811 SOCKLEN_T len = sizeof(error);
812
813 getsockopt(sck->m_endpoint, SOL_SOCKET, SO_ERROR, (void*) &error, &len);
814
815 if (!error)
816*/
817 return GSOCK_NOERROR;
818 }
819 }
820
821 /* If connect failed with EINPROGRESS and the GSocket object
822 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
823 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
824 * this way if the connection completes, a GSOCK_CONNECTION
825 * event will be generated, if enabled.
826 */
827 if ((err == kOTNoDataErr) && (sck->m_non_blocking))
828 {
829 sck->m_error = GSOCK_WOULDBLOCK;
830 return GSOCK_WOULDBLOCK;
831 }
832
833 /* If connect failed with an error other than EINPROGRESS,
834 * then the call to GSocket_Connect has failed.
835 */
836 OTSndOrderlyDisconnect( sck->m_endpoint ) ;
837
838 sck->m_endpoint = kOTInvalidEndpointRef ;
839 sck->m_error = GSOCK_IOERR;
840 return GSOCK_IOERR;
841 }
842// OTInetEventHandler(sck, T_CONNECT , kOTNoError , NULL ) ;
843 return GSOCK_NOERROR;
844}
845
846/* Generic IO */
847
848/* Like recv(), send(), ... */
849int GSocket_Read(GSocket *socket, char *buffer, int size)
850{
851 int ret = 0 ;
852
853 assert(socket != NULL);
854
855 /* Reenable INPUT events */
856 socket->m_detected &= ~GSOCK_INPUT_FLAG;
857
858 if (socket->m_endpoint == kOTInvalidEndpointRef || socket->m_server)
859 {
860 socket->m_error = GSOCK_INVSOCK;
861 return -1;
862 }
863
864 /* If the socket is blocking, wait for data (with a timeout) */
865 if (_GSocket_Input_Timeout(socket) == GSOCK_TIMEDOUT)
866 return -1;
867
868 /* Read the data */
869 if (socket->m_stream)
870 ret = _GSocket_Recv_Stream(socket, buffer, size);
871 else
872 ret = _GSocket_Recv_Dgram(socket, buffer, size);
873
874 if (ret == -1)
875 {
876 if (errno == EWOULDBLOCK)
877 socket->m_error = GSOCK_WOULDBLOCK;
878 else
879 socket->m_error = GSOCK_IOERR;
880 }
881
882 return ret;
883}
884
885int GSocket_Write(GSocket *socket, const char *buffer, int size)
886{
887 int ret;
888
889 assert(socket != NULL);
890
891 if (socket->m_endpoint == kOTInvalidEndpointRef || socket->m_server)
892 {
893 socket->m_error = GSOCK_INVSOCK;
894 return -1;
895 }
896
897 /* If the socket is blocking, wait for writability (with a timeout) */
898 if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
899 return -1;
900
901 /* Write the data */
902 if (socket->m_stream)
903 ret = _GSocket_Send_Stream(socket, buffer, size);
904 else
905 ret = _GSocket_Send_Dgram(socket, buffer, size);
906
907 if (ret == -1)
908 {
909 if (errno == EWOULDBLOCK)
910 socket->m_error = GSOCK_WOULDBLOCK;
911 else
912 socket->m_error = GSOCK_IOERR;
913
914 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
915 * in MSW). Once the first OUTPUT event is received, users can assume
916 * that the socket is writable until a read operation fails. Only then
917 * will further OUTPUT events be posted.
918 */
919 socket->m_detected &= ~GSOCK_OUTPUT_FLAG;
920 return -1;
921 }
922
923 return ret;
924}
925
926/* GSocket_Select:
927 * Polls the socket to determine its status. This function will
928 * check for the events specified in the 'flags' parameter, and
929 * it will return a mask indicating which operations can be
930 * performed. This function won't block, regardless of the
931 * mode (blocking | nonblocking) of the socket.
932 */
933GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
934{
935 OTResult state ;
936 assert(socket != NULL);
937 wxMacProcessNotifierEvents() ;
938 /*
939 state = OTGetEndpointState(socket->m_endpoint);
940
941 if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( socket->m_detected & GSOCK_INPUT_FLAG ) )
942 {
943 size_t sz = 0 ;
944 OTCountDataBytes( socket->m_endpoint , &sz ) ;
945 if ( state == T_INCON || sz > 0 )
946 {
947 socket->m_detected |= GSOCK_INPUT_FLAG ;
948 (socket->m_cbacks[GSOCK_INPUT])(socket, GSOCK_INPUT, socket->m_data[GSOCK_INPUT]);
949 }
950 }
951 if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( socket->m_detected & GSOCK_OUTPUT_FLAG ) )
952 {
953 if ( state == T_DATAXFER || state == T_INREL )
954 {
955 socket->m_detected |=GSOCK_OUTPUT_FLAG ;
956 (socket->m_cbacks[GSOCK_OUTPUT])(socket, GSOCK_OUTPUT, socket->m_data[GSOCK_OUTPUT]);
957 }
958 }
959 */
960 return ( flags & socket->m_detected ) ;
961}
962
963/* Flags */
964
965/* GSocket_SetNonBlocking:
966 * Sets the socket to non-blocking mode. All IO calls will return
967 * immediately.
968 */
969void GSocket_SetNonBlocking(GSocket *socket, int non_block)
970{
971 assert(socket != NULL);
972
973 socket->m_non_blocking = non_block;
974}
975
976/* GSocket_SetTimeout:
977 * Sets the timeout for blocking calls. Time is expressed in
978 * milliseconds.
979 */
980void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
981{
982 assert(socket != NULL);
983
79da3092
SC
984// this is usually set too high and we have not yet been able to detect a closed
985// stream, thus we leave the 10 sec timeout
986// socket->m_timeout = millisec;
ee6b1d97
SC
987}
988
989/* GSocket_GetError:
990 * Returns the last error occured for this socket. Note that successful
991 * operations do not clear this back to GSOCK_NOERROR, so use it only
992 * after an error.
993 */
994GSocketError GSocket_GetError(GSocket *socket)
995{
996 assert(socket != NULL);
997
998 return socket->m_error;
999}
1000
1001/* Callbacks */
1002
1003/* GSOCK_INPUT:
1004 * There is data to be read in the input buffer. If, after a read
1005 * operation, there is still data available, the callback function will
1006 * be called again.
1007 * GSOCK_OUTPUT:
1008 * The socket is available for writing. That is, the next write call
1009 * won't block. This event is generated only once, when the connection is
1010 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1011 * when the output buffer empties again. This means that the app should
1012 * assume that it can write since the first OUTPUT event, and no more
1013 * OUTPUT events will be generated unless an error occurs.
1014 * GSOCK_CONNECTION:
1015 * Connection succesfully established, for client sockets, or incoming
1016 * client connection, for server sockets. Wait for this event (also watch
1017 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1018 * GSOCK_LOST:
1019 * The connection is lost (or a connection request failed); this could
1020 * be due to a failure, or due to the peer closing it gracefully.
1021 */
1022
1023/* GSocket_SetCallback:
1024 * Enables the callbacks specified by 'flags'. Note that 'flags'
1025 * may be a combination of flags OR'ed toghether, so the same
1026 * callback function can be made to accept different events.
1027 * The callback function must have the following prototype:
1028 *
1029 * void function(GSocket *socket, GSocketEvent event, char *cdata)
1030 */
1031void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
1032 GSocketCallback callback, char *cdata)
1033{
1034 int count;
1035
1036 assert(socket != NULL);
1037
1038 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1039 {
1040 if ((flags & (1 << count)) != 0)
1041 {
1042 socket->m_cbacks[count] = callback;
1043 socket->m_data[count] = cdata;
1044 }
1045 }
1046}
1047
1048/* GSocket_UnsetCallback:
1049 * Disables all callbacks specified by 'flags', which may be a
1050 * combination of flags OR'ed toghether.
1051 */
1052void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
1053{
1054 int count;
1055
1056 assert(socket != NULL);
1057
1058 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1059 {
1060 if ((flags & (1 << count)) != 0)
1061 {
1062 socket->m_cbacks[count] = NULL;
1063 socket->m_data[count] = NULL;
1064 }
1065 }
1066}
1067
1068
1069#define CALL_CALLBACK(socket, event) { \
1070 _GSocket_Disable(socket, event); \
1071 if (socket->m_cbacks[event]) \
1072 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
1073}
1074
1075int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
1076{
1077 OTFlags flags ;
1078 OTResult res ;
5fde6fcc 1079 OTByteCount sz = 0 ;
ee6b1d97 1080
ee6b1d97 1081 OTCountDataBytes( socket->m_endpoint , &sz ) ;
79da3092
SC
1082 if ( size > sz )
1083 size = sz ;
ee6b1d97
SC
1084 res = OTRcv( socket->m_endpoint , buffer , size , &flags ) ;
1085 if ( res < 0 )
1086 {
1087 return -1 ;
1088 }
1089
1090 // we simulate another read event if there are still bytes
1091 if ( socket->m_takesEvents )
1092 {
5fde6fcc 1093 OTByteCount sz = 0 ;
ee6b1d97
SC
1094 OTCountDataBytes( socket->m_endpoint , &sz ) ;
1095 if ( sz > 0 )
1096 {
1097 socket->m_detected |= GSOCK_INPUT_FLAG ;
1098 (socket->m_cbacks[GSOCK_INPUT])(socket, GSOCK_INPUT, socket->m_data[GSOCK_INPUT]);
1099 }
1100 }
1101 return res ;
1102}
1103
1104int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
1105{
1106// TODO
1107 int ret = -1;
1108#if 0
1109 struct sockaddr from;
1110 SOCKLEN_T fromlen = sizeof(from);
1111 GSocketError err;
1112
1113 fromlen = sizeof(from);
1114
1115 ret = recvfrom(socket->m_endpoint, buffer, size, 0, &from, (SOCKLEN_T *) &fromlen);
1116
1117 if (ret == -1)
1118 return -1;
1119
1120 /* Translate a system address into a GSocket address */
1121 if (!socket->m_peer)
1122 {
1123 socket->m_peer = GAddress_new();
1124 if (!socket->m_peer)
1125 {
1126 socket->m_error = GSOCK_MEMERR;
1127 return -1;
1128 }
1129 }
1130 err = _GAddress_translate_from(socket->m_peer, &from, fromlen);
1131 if (err != GSOCK_NOERROR)
1132 {
1133 GAddress_destroy(socket->m_peer);
1134 socket->m_peer = NULL;
1135 socket->m_error = err;
1136 return -1;
1137 }
1138#endif
1139 return ret;
1140}
1141
1142int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
1143{
1144 OTFlags flags = 0 ;
1145 OTResult res ;
1146
1147 res = OTSnd( socket->m_endpoint , (void*) buffer , size , flags ) ;
1148 return res ;
1149}
1150
1151int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
1152{
1153 int ret = -1 ;
1154// TODO
1155#if 0
1156 struct sockaddr *addr;
1157 int len ;
1158 GSocketError err;
1159
1160 if (!socket->m_peer)
1161 {
1162 socket->m_error = GSOCK_INVADDR;
1163 return -1;
1164 }
1165
1166 err = _GAddress_translate_to(socket->m_peer, &addr, &len);
1167 if (err != GSOCK_NOERROR)
1168 {
1169 socket->m_error = err;
1170 return -1;
1171 }
1172
1173 ret = sendto(socket->m_endpoint, buffer, size, 0, addr, len);
1174
1175 /* Frees memory allocated from _GAddress_translate_to */
1176 free(addr);
1177#endif
1178 return ret;
1179}
1180
1181
1182/*
1183 * -------------------------------------------------------------------------
1184 * GAddress
1185 * -------------------------------------------------------------------------
1186 */
1187
1188/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY
1189 * or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it initalizes address
1190 * to be a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
1191 */
1192#define CHECK_ADDRESS(address, family, retval) \
1193{ \
1194 if (address->m_family == GSOCK_NOFAMILY) \
1195 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1196 return address->m_error; \
1197 if (address->m_family != GSOCK_##family) \
1198 { \
1199 address->m_error = GSOCK_INVADDR; \
1200 return retval; \
1201 } \
1202}
1203
1204GAddress *GAddress_new()
1205{
1206 GAddress *address;
1207
1208 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1209 return NULL;
1210
1211 address->m_family = GSOCK_NOFAMILY;
1212 address->m_host = INADDR_NONE ;
1213 address->m_port = 0 ;
1214
1215 return address;
1216}
1217
1218GAddress *GAddress_copy(GAddress *address)
1219{
1220 GAddress *addr2;
1221
1222 assert(address != NULL);
1223
1224 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1225 return NULL;
1226
1227 memcpy(addr2, address, sizeof(GAddress));
1228 return addr2;
1229}
1230
1231void GAddress_destroy(GAddress *address)
1232{
1233 assert(address != NULL);
1234
1235 free(address);
1236}
1237
1238void GAddress_SetFamily(GAddress *address, GAddressType type)
1239{
1240 assert(address != NULL);
1241
1242 address->m_family = type;
1243}
1244
1245GAddressType GAddress_GetFamily(GAddress *address)
1246{
1247 assert(address != NULL);
1248
1249 return address->m_family;
1250}
1251
1252GSocketError _GAddress_translate_from(GAddress *address,
1253 InetAddress *addr)
1254{
1255 switch (addr->fAddressType)
1256 {
1257 case AF_INET:
1258 address->m_family = GSOCK_INET;
1259 break;
1260#ifdef AF_INET6
1261 case AF_INET6:
1262 address->m_family = GSOCK_INET6;
1263 break;
1264#endif
1265 default:
1266 {
1267 address->m_error = GSOCK_INVOP;
1268 return GSOCK_INVOP;
1269 }
1270 }
1271 address->m_host = addr->fHost ;
1272 address->m_port = addr->fPort ;
1273 return GSOCK_NOERROR;
1274}
1275
1276GSocketError _GAddress_translate_to(GAddress *address,
1277 InetAddress *addr)
1278{
79da3092
SC
1279 if ( GSocket_Verify_Inited() == FALSE )
1280 return GSOCK_IOERR ;
ee6b1d97
SC
1281 memset(addr, 0 , sizeof(struct InetAddress));
1282 OTInitInetAddress( addr , address->m_port , address->m_host ) ;
1283 return GSOCK_NOERROR;
1284}
1285
1286/*
1287 * -------------------------------------------------------------------------
1288 * Internet address family
1289 * -------------------------------------------------------------------------
1290 */
1291
1292GSocketError _GAddress_Init_INET(GAddress *address)
1293{
1294 address->m_family = GSOCK_INET;
1295 address->m_host = kOTAnyInetAddress ;
1296
1297 return GSOCK_NOERROR;
1298}
1299
1300GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1301{
1302 InetHostInfo hinfo ;
1303 OSStatus ret ;
1304
79da3092
SC
1305 if ( GSocket_Verify_Inited() == FALSE )
1306 return GSOCK_IOERR ;
1307
ee6b1d97
SC
1308 assert(address != NULL);
1309
1310 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1311 ret = OTInetStringToAddress( gInetSvcRef , (char*) hostname , &hinfo ) ;
1312 if ( ret != kOTNoError )
1313 {
1314 address->m_host = INADDR_NONE ;
1315 address->m_error = GSOCK_NOHOST;
1316 return GSOCK_NOHOST;
1317 }
1318 address->m_host = hinfo.addrs[0] ;
1319 return GSOCK_NOERROR;
1320}
1321
1322GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1323{
1324 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1325}
1326
1327GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1328 unsigned long hostaddr)
1329{
1330 struct in_addr *addr;
1331
1332 assert(address != NULL);
1333
1334 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1335
1336 address->m_host = hostaddr ;
1337
1338 return GSOCK_NOERROR;
1339}
1340
1341struct service_entry
1342{
1343 char * name ;
1344 unsigned short port ;
1345 char * protocol ;
1346} ;
1347typedef struct service_entry service_entry ;
1348
1349service_entry gServices[] =
1350{
1351 { "http" , 80 , "tcp" }
1352} ;
1353
1354GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1355 const char *protocol)
1356{
1357 InetAddress *addr;
1358 int i ;
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{
1392 InetAddress *addr;
1393
1394 assert(address != NULL);
1395 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1396 address->m_port = port ;
1397
1398 return GSOCK_NOERROR;
1399}
1400
1401GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1402{
1403 InetDomainName name ;
79da3092
SC
1404 if ( GSocket_Verify_Inited() == FALSE )
1405 return GSOCK_IOERR ;
ee6b1d97
SC
1406
1407 assert(address != NULL);
1408 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1409
5fde6fcc 1410 OTInetAddressToName( gInetSvcRef , address->m_host , name ) ;
ee6b1d97
SC
1411 strncpy( hostname , name , sbuf ) ;
1412 return GSOCK_NOERROR;
1413}
1414
1415unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1416{
1417 assert(address != NULL);
1418 CHECK_ADDRESS(address, INET, 0);
1419
1420 return address->m_host;
1421}
1422
1423unsigned short GAddress_INET_GetPort(GAddress *address)
1424{
1425 assert(address != NULL);
1426 CHECK_ADDRESS(address, INET, 0);
1427
1428 return address->m_port;
1429}
1430
1431void _GSocket_Enable_Events(GSocket *socket)
1432{
1433 if ( socket->m_takesEvents )
1434 return ;
1435
1436 {
1437 OTResult state ;
1438 socket->m_takesEvents = TRUE ;
1439 state = OTGetEndpointState(socket->m_endpoint);
1440
1441 {
5fde6fcc 1442 OTByteCount sz = 0 ;
ee6b1d97
SC
1443 OTCountDataBytes( socket->m_endpoint , &sz ) ;
1444 if ( state == T_INCON || sz > 0 )
1445 {
1446 socket->m_detected |= GSOCK_INPUT_FLAG ;
1447 (socket->m_cbacks[GSOCK_INPUT])(socket, GSOCK_INPUT, socket->m_data[GSOCK_INPUT]);
1448 }
1449 }
1450 {
1451 if ( state == T_DATAXFER || state == T_INREL )
1452 {
1453 socket->m_detected |=GSOCK_OUTPUT_FLAG ;
1454 (socket->m_cbacks[GSOCK_OUTPUT])(socket, GSOCK_OUTPUT, socket->m_data[GSOCK_OUTPUT]);
1455 }
1456 }
1457 }
1458}
1459
1460void _GSocket_Disable_Events(GSocket *socket)
1461{
1462 socket->m_takesEvents = FALSE ;
1463}
1464
1465/* _GSocket_Input_Timeout:
1466 * For blocking sockets, wait until data is available or
1467 * until timeout ellapses.
1468 */
1469GSocketError _GSocket_Input_Timeout(GSocket *socket)
1470{
1471 if ( !socket->m_non_blocking )
1472 {
1473 UnsignedWide now , start ;
1474 short formerTakesEvents = socket->m_takesEvents ;
1475 Microseconds(&start);
1476 now = start ;
1477 socket->m_takesEvents = FALSE ;
1478
1479 while( (now.hi * 4294967296.0 + now.lo) - (start.hi * 4294967296.0 + start.lo) < socket->m_timeout * 1000.0 )
1480 {
1481 OTResult state ;
5fde6fcc 1482 OTByteCount sz = 0 ;
62e83765 1483 state = OTGetEndpointState(socket->m_endpoint);
ee6b1d97
SC
1484
1485 OTCountDataBytes( socket->m_endpoint , &sz ) ;
1486 if ( state == T_INCON || sz > 0 )
1487 {
1488 socket->m_takesEvents = formerTakesEvents ;
1489 return GSOCK_NOERROR;
1490 }
1491 Microseconds(&now);
1492 }
1493 socket->m_takesEvents = formerTakesEvents ;
1494 socket->m_error = GSOCK_TIMEDOUT;
1495 return GSOCK_TIMEDOUT;
1496 }
1497 return GSOCK_NOERROR;
1498}
1499
1500/* _GSocket_Output_Timeout:
1501 * For blocking sockets, wait until data can be sent without
1502 * blocking or until timeout ellapses.
1503 */
1504GSocketError _GSocket_Output_Timeout(GSocket *socket)
1505{
1506 if ( !socket->m_non_blocking )
1507 {
1508 UnsignedWide now , start ;
1509 short formerTakesEvents = socket->m_takesEvents ;
1510 Microseconds(&start);
1511 now = start ;
1512 socket->m_takesEvents = FALSE ;
1513
1514 while( (now.hi * 4294967296.0 + now.lo) - (start.hi * 4294967296.0 + start.lo) < socket->m_timeout * 1000.0 )
1515 {
1516 OTResult state ;
1517 state = OTGetEndpointState(socket->m_endpoint);
1518
1519 if ( state == T_DATAXFER || state == T_INREL )
1520 {
1521 socket->m_takesEvents = formerTakesEvents ;
1522 return GSOCK_NOERROR;
1523 }
1524 Microseconds(&now);
1525 }
1526 socket->m_takesEvents = formerTakesEvents ;
1527 socket->m_error = GSOCK_TIMEDOUT;
1528 return GSOCK_TIMEDOUT;
1529 }
1530 return GSOCK_NOERROR;
1531}
1532
1533/* GSOCK_INPUT:
1534 * There is data to be read in the input buffer. If, after a read
1535 * operation, there is still data available, the callback function will
1536 * be called again.
1537 * GSOCK_OUTPUT:
1538 * The socket is available for writing. That is, the next write call
1539 * won't block. This event is generated only once, when the connection is
1540 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1541 * when the output buffer empties again. This means that the app should
1542 * assume that it can write since the first OUTPUT event, and no more
1543 * OUTPUT events will be generated unless an error occurs.
1544 * GSOCK_CONNECTION:
1545 * Connection succesfully established, for client sockets, or incoming
1546 * client connection, for server sockets. Wait for this event (also watch
1547 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1548 * GSOCK_LOST:
1549 * The connection is lost (or a connection request failed); this could
1550 * be due to a failure, or due to the peer closing it gracefully.
1551 */
1552
1553void _GSocket_Internal_Proc(unsigned long e , void* d )
1554{
1555
1556 GSocket * socket = (GSocket*) d ;
1557 OTEventCode ev = (OTEventCode) e ;
1558 GSocketEvent event;
1559 GSocketEvent event2;
1560 GSocketCallback cback;
1561 char *data;
1562 GSocketCallback cback2;
1563 char *data2;
1564
1565 if ( !socket )
1566 return ;
1567 event = GSOCK_MAX_EVENT ;
1568 event2 = GSOCK_MAX_EVENT ;
1569 cback = NULL;
1570 data = NULL;
1571 cback2 = NULL;
1572 data2 = NULL;
1573
1574 /* Check that the socket still exists (it has not been
1575 * destroyed) and for safety, check that the m_endpoint field
1576 * is what we expect it to be.
1577 */
1578 if ((socket != NULL) && (socket->m_takesEvents))
1579 {
1580 switch (ev)
1581 {
1582 case T_LISTEN :
1583 event = GSOCK_CONNECTION ;
1584 break ;
1585 case T_CONNECT :
1586 event = GSOCK_CONNECTION ;
1587 event2 = GSOCK_OUTPUT ;
1588 {
1589 TCall retCall;
1590
1591 retCall.addr.buf = NULL;
1592 retCall.addr.maxlen = 0;
1593 retCall.opt.buf = NULL;
1594 retCall.opt.maxlen = 0;
1595 retCall.udata.buf = NULL;
1596 retCall.udata.maxlen= 0;
1597 OTRcvConnect( socket->m_endpoint , &retCall ) ;
1598 }
1599 break ;
1600 case T_DISCONNECT :
1601 event = GSOCK_LOST ;
1602 break ;
1603 case T_GODATA :
1604 case T_GOEXDATA :
1605 event = GSOCK_OUTPUT ;
1606 break ;
1607 case T_DATA :
1608 event = GSOCK_INPUT ;
1609 break ;
1610 case T_EXDATA :
1611 event = GSOCK_INPUT ;
1612 break ;
1613 }
1614 if (event != GSOCK_MAX_EVENT)
1615 {
1616 cback = socket->m_cbacks[event];
1617 data = socket->m_data[event];
1618
1619 if (event == GSOCK_LOST)
1620 socket->m_detected = GSOCK_LOST_FLAG;
1621 else
1622 socket->m_detected |= (1 << event);
1623 }
1624 if (event2 != GSOCK_MAX_EVENT)
1625 {
1626 cback2 = socket->m_cbacks[event2];
1627 data2 = socket->m_data[event2];
1628
1629 if (event2 == GSOCK_LOST)
1630 socket->m_detected = GSOCK_LOST_FLAG;
1631 else
1632 socket->m_detected |= (1 << event2);
1633 }
1634 }
1635
1636 /* OK, we can now leave the critical section because we have
1637 * already obtained the callback address (we make no further
1638 * accesses to socket->whatever). However, the app should
1639 * be prepared to handle events from a socket that has just
1640 * been closed!
1641 */
1642
1643 if (cback != NULL)
1644 (cback)(socket, event, data);
1645 if (cback2 != NULL)
1646 (cback2)(socket, event2, data2);
1647
1648}
1649
03e11df5
GD
1650/* Hack added for Mac OS X */
1651GSocketError GAddress_UNIX_GetPath(GAddress *addr, char *path, size_t buf)
1652{
1653}
1654
1655GSocketError GAddress_UNIX_SetPath(GAddress *addr, const char *path)
1656{
1657}
1658
ee6b1d97 1659#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */