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