]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/cfsocket.cpp
cleanup:
[wxWidgets.git] / src / mac / carbon / cfsocket.cpp
CommitLineData
56d061c5 1/////////////////////////////////////////////////////////////////////////////
f3078f07 2// Name: src/mac/carbon/cfsocket.cpp
56d061c5
SC
3// Purpose: Socket handler classes
4// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
5// Created: April 1997
6// Copyright: (C) 1999-1997, Guilhem Lavaux
7// (C) 2000-1999, Guillermo Rodriguez Garcia
8// RCS_ID: $Id$
65571936 9// License: see wxWindows licence
56d061c5
SC
10/////////////////////////////////////////////////////////////////////////////
11
56d061c5
SC
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
8e3f3880 15 #pragma hdrstop
56d061c5
SC
16#endif
17
18#if wxUSE_SOCKETS
19
df91131c
WS
20#include "wx/socket.h"
21
8e3f3880
WS
22#ifndef WX_PRECOMP
23 #include "wx/object.h"
df91131c 24 #include "wx/string.h"
88a7a4e1 25 #include "wx/intl.h"
e4db172a 26 #include "wx/log.h"
d5da0ce7 27 #include "wx/event.h"
670f9935 28 #include "wx/app.h"
de6185e2 29 #include "wx/utils.h"
c0badb70 30 #include "wx/timer.h"
02761f6c 31 #include "wx/module.h"
8e3f3880
WS
32#endif
33
56d061c5 34#include "wx/apptrait.h"
56d061c5
SC
35
36#include "wx/sckaddr.h"
56d061c5
SC
37#include "wx/mac/carbon/private.h"
38
39#include <sys/socket.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43
44#define HAVE_INET_ATON
45
46// DLL options compatibility check:
47#include "wx/build.h"
f3078f07 48
56d061c5
SC
49WX_CHECK_BUILD_OPTIONS("wxNet")
50
56d061c5
SC
51
52// discard buffer
53#define MAX_DISCARD_SIZE (10 * 1024)
54
55#ifndef INVALID_SOCKET
56#define INVALID_SOCKET -1
57#endif
58
59// what to do within waits: we have 2 cases: from the main thread itself we
60// have to call wxYield() to let the events (including the GUI events and the
77ffb593 61// low-level (not wxWidgets) events from GSocket) be processed. From another
56d061c5
SC
62// thread it is enough to just call wxThread::Yield() which will give away the
63// rest of our time slice: the explanation is that the events will be processed
64// by the main thread anyhow, without calling wxYield(), but we don't want to
65// eat the CPU time uselessly while sitting in the loop waiting for the data
66#if wxUSE_THREADS
67 #define PROCESS_EVENTS() \
68 { \
69 if ( wxThread::IsMain() ) \
70 wxYield(); \
71 else \
72 wxThread::Yield(); \
73 }
74#else // !wxUSE_THREADS
75 #define PROCESS_EVENTS() wxYield()
76#endif // wxUSE_THREADS/!wxUSE_THREADS
77
78#define wxTRACE_Socket _T("wxSocket")
79
56d061c5
SC
80
81IMPLEMENT_CLASS(wxSocketBase, wxObject)
82IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
83IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
84IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
85IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
86
87// --------------------------------------------------------------------------
88// private classes
89// --------------------------------------------------------------------------
90
91class wxSocketState : public wxObject
92{
93public:
94 wxSocketFlags m_flags;
95 wxSocketEventFlags m_eventmask;
96 bool m_notify;
97 void *m_clientData;
98
99public:
100 wxSocketState() : wxObject() {}
101
102 DECLARE_NO_COPY_CLASS(wxSocketState)
103};
104
105struct _GSocket
106{
107 CFSocketNativeHandle m_fd;
108 GAddress *m_local;
109 GAddress *m_peer;
110 GSocketError m_error;
111
112 int m_non_blocking;
113 int m_server;
114 int m_stream;
115 int m_oriented;
116 int m_establishing;
117 unsigned long m_timeout;
118
f3078f07 119 // Callbacks
56d061c5
SC
120 GSocketEventFlags m_detected;
121 GSocketCallback m_cbacks[GSOCK_MAX_EVENT];
122 char *m_data[GSOCK_MAX_EVENT];
123
124 CFSocketRef m_cfSocket;
125 CFRunLoopSourceRef m_runLoopSource;
126 CFReadStreamRef m_readStream ;
127 CFWriteStreamRef m_writeStream ;
f3078f07 128};
56d061c5
SC
129
130struct _GAddress
131{
132 struct sockaddr *m_addr;
133 size_t m_len;
134
135 GAddressType m_family;
136 int m_realfamily;
137
138 GSocketError m_error;
139 int somethingElse ;
140};
141
142void wxMacCFSocketCallback(CFSocketRef s, CFSocketCallBackType callbackType,
143 CFDataRef address, const void* data, void* info) ;
144void _GSocket_Enable(GSocket *socket, GSocketEvent event) ;
145void _GSocket_Disable(GSocket *socket, GSocketEvent event) ;
146
147// ==========================================================================
148// wxSocketBase
149// ==========================================================================
150
151// --------------------------------------------------------------------------
152// Initialization and shutdown
153// --------------------------------------------------------------------------
154
155// FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
156// to m_countInit with a crit section
157size_t wxSocketBase::m_countInit = 0;
158
159bool wxSocketBase::IsInitialized()
160{
161 return m_countInit > 0;
162}
163
164bool wxSocketBase::Initialize()
165{
166 if ( !m_countInit++ )
167 {
168#if 0
169 wxAppTraits *traits = wxAppConsole::GetInstance() ?
170 wxAppConsole::GetInstance()->GetTraits() : NULL;
f3078f07 171 GSocketGUIFunctionsTable *functions =
56d061c5
SC
172 traits ? traits->GetSocketGUIFunctionsTable() : NULL;
173 GSocket_SetGUIFunctions(functions);
f3078f07 174
56d061c5
SC
175 if ( !GSocket_Init() )
176 {
177 m_countInit--;
178
f3078f07 179 return false;
56d061c5
SC
180 }
181#endif
182 }
183
f3078f07 184 return true;
56d061c5
SC
185}
186
187void wxSocketBase::Shutdown()
188{
189 // we should be initialized
f3078f07 190 wxASSERT_MSG( m_countInit, wxT("extra call to Shutdown()") );
56d061c5
SC
191 if ( !--m_countInit )
192 {
193#if 0
194 GSocket_Cleanup();
195#endif
196 }
197}
198
199// --------------------------------------------------------------------------
200// Ctor and dtor
201// --------------------------------------------------------------------------
202
203void wxSocketBase::Init()
204{
205 m_socket = NULL;
206 m_type = wxSOCKET_UNINIT;
207
208 // state
209 m_flags = 0;
210 m_connected =
211 m_establishing =
212 m_reading =
213 m_writing =
f3078f07 214 m_error = false;
56d061c5
SC
215 m_lcount = 0;
216 m_timeout = 600;
f3078f07 217 m_beingDeleted = false;
56d061c5
SC
218
219 // pushback buffer
220 m_unread = NULL;
221 m_unrd_size = 0;
222 m_unrd_cur = 0;
223
224 // events
225 m_id = -1;
226 m_handler = NULL;
227 m_clientData = NULL;
f3078f07 228 m_notify = false;
56d061c5
SC
229 m_eventmask = 0;
230
231 if ( !IsInitialized() )
232 {
233 // this Initialize() will be undone by wxSocketModule::OnExit(), all the
234 // other calls to it should be matched by a call to Shutdown()
235 Initialize();
236 }
237}
238
239wxSocketBase::wxSocketBase()
240{
241 Init();
242}
243
f3078f07 244wxSocketBase::wxSocketBase( wxSocketFlags flags, wxSocketType type)
56d061c5
SC
245{
246 Init();
247
248 m_flags = flags;
249 m_type = type;
250}
251
252wxSocketBase::~wxSocketBase()
253{
254 // Just in case the app called Destroy() *and* then deleted
255 // the socket immediately: don't leave dangling pointers.
256 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
257 if ( traits )
258 traits->RemoveFromPendingDelete(this);
259
260 // Shutdown and close the socket
261 if (!m_beingDeleted)
262 Close();
263
264 // Destroy the GSocket object
265 if (m_socket)
266 {
267 GSocket_destroy(m_socket);
268 }
269
270 // Free the pushback buffer
271 if (m_unread)
272 free(m_unread);
273}
274
275bool wxSocketBase::Destroy()
276{
277 // Delayed destruction: the socket will be deleted during the next
278 // idle loop iteration. This ensures that all pending events have
279 // been processed.
f3078f07 280 m_beingDeleted = true;
56d061c5
SC
281
282 // Shutdown and close the socket
283 Close();
284
285 // Supress events from now on
f3078f07 286 Notify(false);
56d061c5
SC
287
288 // schedule this object for deletion
289 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
290 if ( traits )
291 {
292 // let the traits object decide what to do with us
293 traits->ScheduleForDestroy(this);
294 }
295 else // no app or no traits
296 {
297 // in wxBase we might have no app object at all, don't leak memory
298 delete this;
299 }
300
f3078f07 301 return true;
56d061c5
SC
302}
303
304// --------------------------------------------------------------------------
305// Basic IO calls
306// --------------------------------------------------------------------------
307
308// The following IO operations update m_error and m_lcount:
309// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
310//
311// TODO: Should Connect, Accept and AcceptWith update m_error?
312
313bool wxSocketBase::Close()
314{
315 // Interrupt pending waits
316 InterruptWait();
317
318 if (m_socket)
56d061c5 319 GSocket_Shutdown(m_socket);
56d061c5 320
f3078f07
DS
321 m_connected = false;
322 m_establishing = false;
323
324 return true;
56d061c5
SC
325}
326
327wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
328{
329 // Mask read events
f3078f07 330 m_reading = true;
56d061c5
SC
331
332 m_lcount = _Read(buffer, nbytes);
333
334 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
335 if (m_flags & wxSOCKET_WAITALL)
336 m_error = (m_lcount != nbytes);
337 else
338 m_error = (m_lcount == 0);
339
340 // Allow read events from now on
f3078f07 341 m_reading = false;
56d061c5
SC
342
343 return *this;
344}
345
346wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
347{
348 int total = 0;
349
350 // Try the pushback buffer first
f3078f07 351 total = GetPushback(buffer, nbytes, false);
56d061c5
SC
352 nbytes -= total;
353 buffer = (char *)buffer + total;
354
355 // Return now in one of the following cases:
356 // - the socket is invalid,
357 // - we got all the data,
358 // - we got *some* data and we are not using wxSOCKET_WAITALL.
359 if ( !m_socket ||
360 !nbytes ||
361 ((total != 0) && !(m_flags & wxSOCKET_WAITALL)) )
362 return total;
363
364 // Possible combinations (they are checked in this order)
365 // wxSOCKET_NOWAIT
366 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
367 // wxSOCKET_BLOCK
368 // wxSOCKET_NONE
369 //
370
371 int ret;
372 if (m_flags & wxSOCKET_NOWAIT)
373 {
374 GSocket_SetNonBlocking(m_socket, 1);
375 ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
376 GSocket_SetNonBlocking(m_socket, 0);
377
378 if (ret > 0)
379 total += ret;
380 }
381 else
382 {
f3078f07 383 bool more = true;
56d061c5
SC
384
385 while (more)
386 {
387 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
388 break;
389
390 ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
391
392 if (ret > 0)
393 {
394 total += ret;
395 nbytes -= ret;
396 buffer = (char *)buffer + ret;
397 }
398
399 // If we got here and wxSOCKET_WAITALL is not set, we can leave
400 // now. Otherwise, wait until we recv all the data or until there
401 // is an error.
402 //
403 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
404 }
405 }
406
407 return total;
408}
409
410wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
411{
412 wxUint32 len, len2, sig, total;
413 bool error;
414 int old_flags;
415 struct
416 {
417 unsigned char sig[4];
418 unsigned char len[4];
f3078f07
DS
419 }
420 msg;
56d061c5
SC
421
422 // Mask read events
f3078f07 423 m_reading = true;
56d061c5
SC
424
425 total = 0;
f3078f07 426 error = true;
56d061c5
SC
427 old_flags = m_flags;
428 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
429
430 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
431 goto exit;
432
433 sig = (wxUint32)msg.sig[0];
434 sig |= (wxUint32)(msg.sig[1] << 8);
435 sig |= (wxUint32)(msg.sig[2] << 16);
436 sig |= (wxUint32)(msg.sig[3] << 24);
437
438 if (sig != 0xfeeddead)
439 {
f3078f07 440 wxLogWarning( wxT("wxSocket: invalid signature in ReadMsg.") );
56d061c5
SC
441 goto exit;
442 }
443
444 len = (wxUint32)msg.len[0];
445 len |= (wxUint32)(msg.len[1] << 8);
446 len |= (wxUint32)(msg.len[2] << 16);
447 len |= (wxUint32)(msg.len[3] << 24);
448
449 if (len > nbytes)
450 {
451 len2 = len - nbytes;
452 len = nbytes;
453 }
454 else
455 len2 = 0;
456
457 // Don't attemp to read if the msg was zero bytes long.
458 if (len)
459 {
460 total = _Read(buffer, len);
461
462 if (total != len)
463 goto exit;
464 }
465 if (len2)
466 {
467 char *discard_buffer = new char[MAX_DISCARD_SIZE];
468 long discard_len;
469
470 // NOTE: discarded bytes don't add to m_lcount.
471 do
472 {
473 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
474 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
475 len2 -= (wxUint32)discard_len;
476 }
477 while ((discard_len > 0) && len2);
478
479 delete [] discard_buffer;
480
481 if (len2 != 0)
482 goto exit;
483 }
484 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
485 goto exit;
486
487 sig = (wxUint32)msg.sig[0];
488 sig |= (wxUint32)(msg.sig[1] << 8);
489 sig |= (wxUint32)(msg.sig[2] << 16);
490 sig |= (wxUint32)(msg.sig[3] << 24);
491
492 if (sig != 0xdeadfeed)
493 {
f3078f07 494 wxLogWarning( wxT("wxSocket: invalid signature in ReadMsg.") );
56d061c5
SC
495 goto exit;
496 }
497
498 // everything was OK
f3078f07 499 error = false;
56d061c5
SC
500
501exit:
502 m_error = error;
503 m_lcount = total;
f3078f07 504 m_reading = false;
56d061c5
SC
505 SetFlags(old_flags);
506
507 return *this;
508}
509
510wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
511{
512 // Mask read events
f3078f07 513 m_reading = true;
56d061c5
SC
514
515 m_lcount = _Read(buffer, nbytes);
516 Pushback(buffer, m_lcount);
517
518 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
519 if (m_flags & wxSOCKET_WAITALL)
520 m_error = (m_lcount != nbytes);
521 else
522 m_error = (m_lcount == 0);
523
524 // Allow read events again
f3078f07 525 m_reading = false;
56d061c5
SC
526
527 return *this;
528}
529
530wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
531{
532 // Mask write events
f3078f07 533 m_writing = true;
56d061c5
SC
534
535 m_lcount = _Write(buffer, nbytes);
536
537 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
538 if (m_flags & wxSOCKET_WAITALL)
539 m_error = (m_lcount != nbytes);
540 else
541 m_error = (m_lcount == 0);
542
543 // Allow write events again
f3078f07 544 m_writing = false;
56d061c5
SC
545
546 return *this;
547}
548
549wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
550{
551 wxUint32 total = 0;
552
553 // If the socket is invalid or parameters are ill, return immediately
554 if (!m_socket || !buffer || !nbytes)
555 return 0;
556
557 // Possible combinations (they are checked in this order)
558 // wxSOCKET_NOWAIT
559 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
560 // wxSOCKET_BLOCK
561 // wxSOCKET_NONE
562 //
563 int ret;
564 if (m_flags & wxSOCKET_NOWAIT)
565 {
566 GSocket_SetNonBlocking(m_socket, 1);
567 ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
568 GSocket_SetNonBlocking(m_socket, 0);
569
570 if (ret > 0)
571 total = ret;
572 }
573 else
574 {
f3078f07 575 bool more = true;
56d061c5
SC
576
577 while (more)
578 {
579 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
580 break;
581
582 ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
583
584 if (ret > 0)
585 {
586 total += ret;
587 nbytes -= ret;
588 buffer = (const char *)buffer + ret;
589 }
590
591 // If we got here and wxSOCKET_WAITALL is not set, we can leave
592 // now. Otherwise, wait until we send all the data or until there
593 // is an error.
594 //
595 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
596 }
597 }
598
599 return total;
600}
601
602wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
603{
604 wxUint32 total;
605 bool error;
606 struct
607 {
608 unsigned char sig[4];
609 unsigned char len[4];
f3078f07
DS
610 }
611 msg;
56d061c5
SC
612
613 // Mask write events
f3078f07 614 m_writing = true;
56d061c5 615
f3078f07 616 error = true;
56d061c5
SC
617 total = 0;
618 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
619
620 msg.sig[0] = (unsigned char) 0xad;
621 msg.sig[1] = (unsigned char) 0xde;
622 msg.sig[2] = (unsigned char) 0xed;
623 msg.sig[3] = (unsigned char) 0xfe;
624
625 msg.len[0] = (unsigned char) (nbytes & 0xff);
626 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
627 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
628 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
629
630 if (_Write(&msg, sizeof(msg)) < sizeof(msg))
631 goto exit;
632
633 total = _Write(buffer, nbytes);
634
635 if (total < nbytes)
636 goto exit;
637
638 msg.sig[0] = (unsigned char) 0xed;
639 msg.sig[1] = (unsigned char) 0xfe;
640 msg.sig[2] = (unsigned char) 0xad;
641 msg.sig[3] = (unsigned char) 0xde;
642 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
643
644 if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
645 goto exit;
646
647 // everything was OK
f3078f07 648 error = false;
56d061c5
SC
649
650exit:
651 m_error = error;
652 m_lcount = total;
f3078f07 653 m_writing = false;
56d061c5
SC
654
655 return *this;
656}
657
658wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
659{
660 if (nbytes != 0)
661 Pushback(buffer, nbytes);
662
f3078f07 663 m_error = false;
56d061c5
SC
664 m_lcount = nbytes;
665
666 return *this;
667}
668
669wxSocketBase& wxSocketBase::Discard()
670{
671 char *buffer = new char[MAX_DISCARD_SIZE];
672 wxUint32 ret;
673 wxUint32 total = 0;
674
675 // Mask read events
f3078f07 676 m_reading = true;
56d061c5
SC
677
678 SetFlags(wxSOCKET_NOWAIT);
679
680 do
681 {
682 ret = _Read(buffer, MAX_DISCARD_SIZE);
683 total += ret;
684 }
685 while (ret == MAX_DISCARD_SIZE);
686
687 delete[] buffer;
688 m_lcount = total;
f3078f07 689 m_error = false;
56d061c5
SC
690
691 // Allow read events again
f3078f07 692 m_reading = false;
56d061c5
SC
693
694 return *this;
695}
696
697// --------------------------------------------------------------------------
698// Wait functions
699// --------------------------------------------------------------------------
700
701// All Wait functions poll the socket using GSocket_Select() to
702// check for the specified combination of conditions, until one
703// of these conditions become true, an error occurs, or the
704// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
705// this won't block the GUI.
706
707bool wxSocketBase::_Wait(long seconds,
708 long milliseconds,
709 wxSocketEventFlags flags)
f3078f07 710{
56d061c5
SC
711 GSocketEventFlags result;
712 long timeout;
713
f3078f07
DS
714 // Set this to true to interrupt ongoing waits
715 m_interrupt = false;
56d061c5
SC
716
717 // Check for valid socket
718 if (!m_socket)
f3078f07 719 return false;
56d061c5
SC
720
721 // Check for valid timeout value.
722 if (seconds != -1)
723 timeout = seconds * 1000 + milliseconds;
724 else
725 timeout = m_timeout * 1000;
726
727#if !defined(wxUSE_GUI) || !wxUSE_GUI
728 GSocket_SetTimeout(m_socket, timeout);
f3078f07 729#endif
56d061c5
SC
730
731 // Wait in an active polling loop.
732 //
733 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
734 // hurt. It has to be here because the (GSocket) event might arrive
735 // a bit delayed, and it has to be in OnRequest as well because we
736 // don't know whether the Wait functions are being used.
737 //
738 // Do this at least once (important if timeout == 0, when
739 // we are just polling). Also, if just polling, do not yield.
740
741 wxStopWatch chrono;
f3078f07 742 bool done = false;
56d061c5
SC
743
744 while (!done)
745 {
746 result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG);
747
748 // Incoming connection (server) or connection established (client)
749 if (result & GSOCK_CONNECTION_FLAG)
750 {
f3078f07
DS
751 m_connected = true;
752 m_establishing = false;
753
754 return true;
56d061c5
SC
755 }
756
757 // Data available or output buffer ready
758 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
759 {
f3078f07 760 return true;
56d061c5
SC
761 }
762
763 // Connection lost
764 if (result & GSOCK_LOST_FLAG)
765 {
f3078f07
DS
766 m_connected = false;
767 m_establishing = false;
768
56d061c5
SC
769 return (flags & GSOCK_LOST_FLAG) != 0;
770 }
771
772 // Wait more?
773 if ((!timeout) || (chrono.Time() > timeout) || (m_interrupt))
f3078f07 774 done = true;
56d061c5
SC
775 else
776 PROCESS_EVENTS();
777 }
778
f3078f07 779 return false;
56d061c5
SC
780}
781
782bool wxSocketBase::Wait(long seconds, long milliseconds)
783{
784 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
785 GSOCK_OUTPUT_FLAG |
786 GSOCK_CONNECTION_FLAG |
787 GSOCK_LOST_FLAG);
788}
789
790bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
791{
792 // Check pushback buffer before entering _Wait
793 if (m_unread)
f3078f07 794 return true;
56d061c5
SC
795
796 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
797 // _Wait becuase of the semantics of WaitForRead: a return
f3078f07 798 // value of true means that a GSocket_Read call will return
56d061c5
SC
799 // immediately, not that there is actually data to read.
800
f3078f07 801 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG | GSOCK_LOST_FLAG);
56d061c5
SC
802}
803
804bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
805{
806 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
807}
808
809bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
810{
811 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
812}
813
814// --------------------------------------------------------------------------
815// Miscellaneous
816// --------------------------------------------------------------------------
817
818//
819// Get local or peer address
820//
821
822bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
823{
824 GAddress *peer;
825
826 if (!m_socket)
f3078f07 827 return false;
56d061c5
SC
828
829 peer = GSocket_GetPeer(m_socket);
830
831 // copying a null address would just trigger an assert anyway
832
833 if (!peer)
f3078f07 834 return false;
56d061c5
SC
835
836 addr_man.SetAddress(peer);
837 GAddress_destroy(peer);
838
f3078f07 839 return true;
56d061c5
SC
840}
841
842bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
843{
844#if 0
845 GAddress *local;
846
847 if (!m_socket)
f3078f07 848 return false;
56d061c5
SC
849
850 local = GSocket_GetLocal(m_socket);
851 addr_man.SetAddress(local);
852 GAddress_destroy(local);
853#endif
f3078f07
DS
854
855 return true;
56d061c5
SC
856}
857
858//
859// Save and restore socket state
860//
861
862void wxSocketBase::SaveState()
863{
864 wxSocketState *state;
865
866 state = new wxSocketState();
867
868 state->m_flags = m_flags;
869 state->m_notify = m_notify;
870 state->m_eventmask = m_eventmask;
871 state->m_clientData = m_clientData;
872
873 m_states.Append(state);
874}
875
876void wxSocketBase::RestoreState()
877{
878 wxList::compatibility_iterator node;
879 wxSocketState *state;
880
881 node = m_states.GetLast();
882 if (!node)
883 return;
884
885 state = (wxSocketState *)node->GetData();
886
887 m_flags = state->m_flags;
888 m_notify = state->m_notify;
889 m_eventmask = state->m_eventmask;
890 m_clientData = state->m_clientData;
f3078f07 891
56d061c5
SC
892 m_states.Erase(node);
893 delete state;
894}
895
896//
897// Timeout and flags
898//
899
900void wxSocketBase::SetTimeout(long seconds)
901{
902 m_timeout = seconds;
903
904#if 0
905 if (m_socket)
906 GSocket_SetTimeout(m_socket, m_timeout * 1000);
907#endif
908}
909
910void wxSocketBase::SetFlags(wxSocketFlags flags)
911{
912 m_flags = flags;
913}
914
915
916// --------------------------------------------------------------------------
917// Event handling
918// --------------------------------------------------------------------------
919
920// A note on how events are processed, which is probably the most
921// difficult thing to get working right while keeping the same API
922// and functionality for all platforms.
923//
924// When GSocket detects an event, it calls wx_socket_callback, which in
925// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
926// object. OnRequest does some housekeeping, and if the event is to be
927// propagated to the user, it creates a new wxSocketEvent object and
928// posts it. The event is not processed immediately, but delayed with
929// AddPendingEvent instead. This is necessary in order to decouple the
930// event processing from wx_socket_callback; otherwise, subsequent IO
931// calls made from the user event handler would fail, as gtk callbacks
932// are not reentrant.
933//
934// Note that, unlike events, user callbacks (now deprecated) are _not_
935// decoupled from wx_socket_callback and thus they suffer from a variety
936// of problems. Avoid them where possible and use events instead.
937
938extern "C"
939void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
940 GSocketEvent notification,
941 char *cdata)
942{
943 wxSocketBase *sckobj = (wxSocketBase *)cdata;
944
945 sckobj->OnRequest((wxSocketNotify) notification);
946}
947
948void wxSocketBase::OnRequest(wxSocketNotify notification)
949{
950 // NOTE: We duplicate some of the code in _Wait, but this doesn't
f3078f07
DS
951 // hurt. It has to be here because the (GSocket) event might arrive
952 // a bit delayed, and it has to be in _Wait as well because we don't
953 // know whether the Wait functions are being used.
56d061c5 954
f3078f07 955 switch (notification)
56d061c5
SC
956 {
957 case wxSOCKET_CONNECTION:
f3078f07
DS
958 m_establishing = false;
959 m_connected = true;
56d061c5
SC
960 break;
961
962 // If we are in the middle of a R/W operation, do not
963 // propagate events to users. Also, filter 'late' events
964 // which are no longer valid.
965
966 case wxSOCKET_INPUT:
967 if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
968 return;
969 break;
970
971 case wxSOCKET_OUTPUT:
972 if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
973 return;
974 break;
975
976 case wxSOCKET_LOST:
f3078f07
DS
977 m_connected = false;
978 m_establishing = false;
56d061c5
SC
979 break;
980
981 default:
982 break;
983 }
984
985 // Schedule the event
986
987 wxSocketEventFlags flag = 0;
988 wxUnusedVar(flag);
989 switch (notification)
990 {
f3078f07
DS
991 case GSOCK_INPUT:
992 flag = GSOCK_INPUT_FLAG;
993 break;
994
995 case GSOCK_OUTPUT:
996 flag = GSOCK_OUTPUT_FLAG;
997 break;
998
999 case GSOCK_CONNECTION:
1000 flag = GSOCK_CONNECTION_FLAG;
1001 break;
1002
1003 case GSOCK_LOST:
1004 flag = GSOCK_LOST_FLAG;
1005 break;
1006
56d061c5 1007 default:
f3078f07 1008 wxLogWarning( wxT("wxSocket: unknown event!") );
56d061c5
SC
1009 return;
1010 }
1011
1012 if (((m_eventmask & flag) == flag) && m_notify)
1013 {
1014 if (m_handler)
1015 {
1016 wxSocketEvent event(m_id);
1017 event.m_event = notification;
1018 event.m_clientData = m_clientData;
1019 event.SetEventObject(this);
1020
1021 m_handler->AddPendingEvent(event);
1022 }
1023 }
1024}
1025
1026void wxSocketBase::Notify(bool notify)
1027{
1028 m_notify = notify;
1029}
1030
1031void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1032{
1033 m_eventmask = flags;
1034}
1035
1036void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
1037{
1038 m_handler = &handler;
1039 m_id = id;
1040}
1041
1042// --------------------------------------------------------------------------
1043// Pushback buffer
1044// --------------------------------------------------------------------------
1045
1046void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
1047{
f3078f07
DS
1048 if (!size)
1049 return;
56d061c5
SC
1050
1051 if (m_unread == NULL)
1052 m_unread = malloc(size);
1053 else
1054 {
1055 void *tmp;
1056
1057 tmp = malloc(m_unrd_size + size);
1058 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1059 free(m_unread);
1060
1061 m_unread = tmp;
1062 }
1063
1064 m_unrd_size += size;
1065
1066 memcpy(m_unread, buffer, size);
1067}
1068
1069wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
1070{
1071 if (!m_unrd_size)
1072 return 0;
1073
1074 if (size > (m_unrd_size-m_unrd_cur))
1075 size = m_unrd_size-m_unrd_cur;
1076
1077 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
1078
1079 if (!peek)
1080 {
1081 m_unrd_cur += size;
1082 if (m_unrd_size == m_unrd_cur)
1083 {
1084 free(m_unread);
1085 m_unread = NULL;
1086 m_unrd_size = 0;
1087 m_unrd_cur = 0;
1088 }
1089 }
1090
1091 return size;
1092}
1093
1094
1095// ==========================================================================
1096// wxSocketServer
1097// ==========================================================================
1098
1099// --------------------------------------------------------------------------
1100// Ctor
1101// --------------------------------------------------------------------------
1102
1103wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
1104 wxSocketFlags flags)
1105 : wxSocketBase(flags, wxSOCKET_SERVER)
1106{
f3078f07 1107 wxLogTrace( wxTRACE_Socket, wxT("Opening wxSocketServer") );
56d061c5
SC
1108
1109 m_socket = GSocket_new();
1110
1111 if (!m_socket)
1112 {
f3078f07 1113 wxLogTrace( wxTRACE_Socket, wxT("*** GSocket_new failed") );
56d061c5
SC
1114 return;
1115 }
1116
f3078f07 1117 // Setup the socket as server
56d061c5
SC
1118
1119#if 0
1120 GSocket_SetLocal(m_socket, addr_man.GetAddress());
1121 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
1122 {
1123 GSocket_destroy(m_socket);
1124 m_socket = NULL;
1125
f3078f07 1126 wxLogTrace( wxTRACE_Socket, wxT("*** GSocket_SetServer failed") );
56d061c5
SC
1127 return;
1128 }
1129
1130 GSocket_SetTimeout(m_socket, m_timeout * 1000);
1131 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1132 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1133 wx_socket_callback, (char *)this);
1134#endif
1135}
1136
1137// --------------------------------------------------------------------------
1138// Accept
1139// --------------------------------------------------------------------------
1140
1141bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
1142{
1143 GSocket *child_socket;
1144
1145 if (!m_socket)
f3078f07 1146 return false;
56d061c5 1147
f3078f07 1148 // If wait == false, then the call should be nonblocking.
56d061c5
SC
1149 // When we are finished, we put the socket to blocking mode
1150 // again.
1151
1152#if 0
1153 if (!wait)
1154 GSocket_SetNonBlocking(m_socket, 1);
1155
1156 child_socket = GSocket_WaitConnection(m_socket);
1157
1158 if (!wait)
1159 GSocket_SetNonBlocking(m_socket, 0);
1160
1161 if (!child_socket)
f3078f07 1162 return false;
56d061c5
SC
1163
1164 sock.m_type = wxSOCKET_BASE;
1165 sock.m_socket = child_socket;
f3078f07 1166 sock.m_connected = true;
56d061c5
SC
1167
1168 GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
1169 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1170 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1171 wx_socket_callback, (char *)&sock);
1172#endif
f3078f07
DS
1173
1174 return true;
56d061c5
SC
1175}
1176
1177wxSocketBase *wxSocketServer::Accept(bool wait)
1178{
1179 wxSocketBase* sock = new wxSocketBase();
1180
1181 sock->SetFlags(m_flags);
1182
1183 if (!AcceptWith(*sock, wait))
1184 {
1185 sock->Destroy();
1186 sock = NULL;
1187 }
1188
1189 return sock;
1190}
1191
1192bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
1193{
1194 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1195}
1196
1197// ==========================================================================
1198// wxSocketClient
1199// ==========================================================================
1200
1201// --------------------------------------------------------------------------
1202// Ctor and dtor
1203// --------------------------------------------------------------------------
1204
1205wxSocketClient::wxSocketClient(wxSocketFlags flags)
1206 : wxSocketBase(flags, wxSOCKET_CLIENT)
1207{
1208}
1209
1210wxSocketClient::~wxSocketClient()
1211{
1212}
1213
1214// --------------------------------------------------------------------------
1215// Connect
1216// --------------------------------------------------------------------------
1217
1218bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1219{
f3078f07 1220 GSocketError err;
56d061c5
SC
1221
1222 if (m_socket)
1223 {
1224 // Shutdown and destroy the socket
1225 Close();
1226 GSocket_destroy(m_socket);
1227 }
1228
1229 m_socket = GSocket_new();
f3078f07
DS
1230 m_connected = false;
1231 m_establishing = false;
56d061c5
SC
1232
1233 if (!m_socket)
f3078f07 1234 return false;
56d061c5
SC
1235
1236 GSocket_SetTimeout(m_socket, m_timeout * 1000);
1237 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1238 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1239 wx_socket_callback, (char *)this);
1240
f3078f07 1241 // If wait == false, then the call should be nonblocking.
56d061c5
SC
1242 // When we are finished, we put the socket to blocking mode
1243 // again.
1244
1245 if (!wait)
1246 GSocket_SetNonBlocking(m_socket, 1);
1247
1248 GSocket_SetPeer(m_socket, addr_man.GetAddress());
1249 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
1250
1251 if (!wait)
1252 GSocket_SetNonBlocking(m_socket, 0);
1253
1254 if (err != GSOCK_NOERROR)
1255 {
1256 if (err == GSOCK_WOULDBLOCK)
f3078f07 1257 m_establishing = true;
56d061c5 1258
f3078f07 1259 return false;
56d061c5
SC
1260 }
1261
f3078f07
DS
1262 m_connected = true;
1263 return true;
56d061c5
SC
1264}
1265
1266bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
1267{
1268 if (m_connected) // Already connected
f3078f07 1269 return true;
56d061c5
SC
1270
1271 if (!m_establishing || !m_socket) // No connection in progress
f3078f07 1272 return false;
56d061c5 1273
f3078f07 1274 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG | GSOCK_LOST_FLAG);
56d061c5
SC
1275}
1276
1277// ==========================================================================
1278// wxDatagramSocket
1279// ==========================================================================
1280
1281/* NOTE: experimental stuff - might change */
1282
1283wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr,
1284 wxSocketFlags flags )
1285 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
1286{
1287#if 0
1288 // Create the socket
1289 m_socket = GSocket_new();
1290
f3078f07 1291 if (!m_socket)
56d061c5
SC
1292 return;
1293
1294 // Setup the socket as non connection oriented
1295 GSocket_SetLocal(m_socket, addr.GetAddress());
1296 if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
1297 {
1298 GSocket_destroy(m_socket);
1299 m_socket = NULL;
1300 return;
1301 }
1302
1303 // Initialize all stuff
f3078f07
DS
1304 m_connected = false;
1305 m_establishing = false;
56d061c5
SC
1306 GSocket_SetTimeout( m_socket, m_timeout );
1307 GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1308 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1309 wx_socket_callback, (char*)this );
1310#endif
1311}
1312
1313wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1314 void* buf,
1315 wxUint32 nBytes )
1316{
1317 Read(buf, nBytes);
1318 GetPeer(addr);
1319 return (*this);
1320}
1321
1322wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
1323 const void* buf,
1324 wxUint32 nBytes )
1325{
1326 GSocket_SetPeer(m_socket, addr.GetAddress());
1327 Write(buf, nBytes);
1328 return (*this);
1329}
1330
1331/*
1332 * -------------------------------------------------------------------------
1333 * GAddress
1334 * -------------------------------------------------------------------------
1335 */
1336
1337/* CHECK_ADDRESS verifies that the current address family is either
1338 * GSOCK_NOFAMILY or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it
1339 * initalizes it to be a GSOCK_*family*. In other cases, it returns
1340 * an appropiate error code.
1341 *
1342 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
1343 */
1344#define CHECK_ADDRESS(address, family) \
1345{ \
1346 if (address->m_family == GSOCK_NOFAMILY) \
1347 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1348 return address->m_error; \
1349 if (address->m_family != GSOCK_##family) \
1350 { \
1351 address->m_error = GSOCK_INVADDR; \
1352 return GSOCK_INVADDR; \
1353 } \
1354}
1355
1356#define CHECK_ADDRESS_RETVAL(address, family, retval) \
1357{ \
1358 if (address->m_family == GSOCK_NOFAMILY) \
1359 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1360 return retval; \
1361 if (address->m_family != GSOCK_##family) \
1362 { \
1363 address->m_error = GSOCK_INVADDR; \
1364 return retval; \
1365 } \
1366}
1367
1368
1369GAddress *GAddress_new(void)
1370{
1371 GAddress *address;
1372
1373 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1374 return NULL;
1375
1376 address->m_family = GSOCK_NOFAMILY;
1377 address->m_addr = NULL;
1378 address->m_len = 0;
1379
1380 return address;
1381}
1382
1383GAddress *GAddress_copy(GAddress *address)
1384{
1385 GAddress *addr2;
1386
1387 assert(address != NULL);
1388
1389 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1390 return NULL;
1391
1392 memcpy(addr2, address, sizeof(GAddress));
1393
1394 if (address->m_addr && address->m_len > 0)
1395 {
1396 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
1397 if (addr2->m_addr == NULL)
1398 {
1399 free(addr2);
1400 return NULL;
1401 }
f3078f07 1402
56d061c5
SC
1403 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1404 }
1405
1406 return addr2;
1407}
1408
1409void GAddress_destroy(GAddress *address)
1410{
f3078f07 1411 assert( address != NULL );
56d061c5
SC
1412
1413 if (address->m_addr)
1414 free(address->m_addr);
1415
1416 free(address);
1417}
1418
1419void GAddress_SetFamily(GAddress *address, GAddressType type)
1420{
1421 assert(address != NULL);
1422
1423 address->m_family = type;
1424}
1425
1426GAddressType GAddress_GetFamily(GAddress *address)
1427{
f3078f07 1428 assert( address != NULL );
56d061c5
SC
1429
1430 return address->m_family;
1431}
1432
1433GSocketError _GAddress_translate_from(GAddress *address,
1434 struct sockaddr *addr, int len)
1435{
1436 address->m_realfamily = addr->sa_family;
1437 switch (addr->sa_family)
1438 {
1439 case AF_INET:
1440 address->m_family = GSOCK_INET;
1441 break;
f3078f07 1442
56d061c5
SC
1443 case AF_UNIX:
1444 address->m_family = GSOCK_UNIX;
1445 break;
f3078f07 1446
56d061c5
SC
1447#ifdef AF_INET6
1448 case AF_INET6:
1449 address->m_family = GSOCK_INET6;
1450 break;
1451#endif
f3078f07 1452
56d061c5
SC
1453 default:
1454 {
1455 address->m_error = GSOCK_INVOP;
1456 return GSOCK_INVOP;
1457 }
1458 }
1459
1460 if (address->m_addr)
1461 free(address->m_addr);
1462
1463 address->m_len = len;
1464 address->m_addr = (struct sockaddr *)malloc(len);
1465
1466 if (address->m_addr == NULL)
1467 {
1468 address->m_error = GSOCK_MEMERR;
1469 return GSOCK_MEMERR;
1470 }
f3078f07 1471
56d061c5
SC
1472 memcpy(address->m_addr, addr, len);
1473
1474 return GSOCK_NOERROR;
1475}
1476
1477GSocketError _GAddress_translate_to(GAddress *address,
1478 struct sockaddr **addr, int *len)
1479{
1480 if (!address->m_addr)
1481 {
1482 address->m_error = GSOCK_INVADDR;
1483 return GSOCK_INVADDR;
1484 }
1485
1486 *len = address->m_len;
1487 *addr = (struct sockaddr *)malloc(address->m_len);
1488 if (*addr == NULL)
1489 {
1490 address->m_error = GSOCK_MEMERR;
1491 return GSOCK_MEMERR;
1492 }
1493
1494 memcpy(*addr, address->m_addr, address->m_len);
1495 return GSOCK_NOERROR;
1496}
1497
1498/*
1499 * -------------------------------------------------------------------------
1500 * Internet address family
1501 * -------------------------------------------------------------------------
1502 */
1503
1504GSocketError _GAddress_Init_INET(GAddress *address)
1505{
1506 address->m_len = sizeof(struct sockaddr_in);
1507 address->m_addr = (struct sockaddr *) malloc(address->m_len);
1508 if (address->m_addr == NULL)
1509 {
1510 address->m_error = GSOCK_MEMERR;
1511 return GSOCK_MEMERR;
1512 }
1513
1514 memset( address->m_addr , 0 , address->m_len ) ;
1515 address->m_family = GSOCK_INET;
1516 address->m_realfamily = PF_INET;
1517 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
1518 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
1519
1520 return GSOCK_NOERROR;
1521}
1522
1523GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1524{
1525 struct hostent *he;
1526 struct in_addr *addr;
1527
f3078f07
DS
1528 assert( address != NULL );
1529 CHECK_ADDRESS( address, INET );
56d061c5
SC
1530
1531 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1532
f3078f07 1533 // If it is a numeric host name, convert it now
56d061c5
SC
1534#if defined(HAVE_INET_ATON)
1535 if (inet_aton(hostname, addr) == 0)
1536 {
1537#elif defined(HAVE_INET_ADDR)
1538 if ( (addr->s_addr = inet_addr(hostname)) == -1 )
1539 {
1540#else
f3078f07 1541 // Use gethostbyname by default
56d061c5 1542#ifndef __WXMAC__
f3078f07 1543 int val = 1; // VA doesn't like constants in conditional expressions
56d061c5
SC
1544 if (val)
1545#endif
1546 {
1547#endif
1548 struct in_addr *array_addr;
1549
f3078f07 1550 // It is a real name, we solve it
56d061c5
SC
1551 if ((he = gethostbyname(hostname)) == NULL)
1552 {
f3078f07 1553 // Reset to invalid address
56d061c5
SC
1554 addr->s_addr = INADDR_NONE;
1555 address->m_error = GSOCK_NOHOST;
1556 return GSOCK_NOHOST;
1557 }
1558 array_addr = (struct in_addr *) *(he->h_addr_list);
1559 addr->s_addr = array_addr[0].s_addr;
1560 }
f3078f07 1561
56d061c5
SC
1562 return GSOCK_NOERROR;
1563}
1564
1565GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1566{
1567 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1568}
1569
1570GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1571 unsigned long hostaddr)
1572{
1573 struct in_addr *addr;
1574
f3078f07
DS
1575 assert( address != NULL );
1576 CHECK_ADDRESS( address, INET );
56d061c5
SC
1577
1578 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1579 addr->s_addr = htonl(hostaddr) ;
1580
1581 return GSOCK_NOERROR;
1582}
1583
1584GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1585 const char *protocol)
1586{
1587 struct servent *se;
1588 struct sockaddr_in *addr;
1589
f3078f07
DS
1590 assert( address != NULL );
1591 CHECK_ADDRESS( address, INET );
56d061c5
SC
1592
1593 if (!port)
1594 {
1595 address->m_error = GSOCK_INVPORT;
1596 return GSOCK_INVPORT;
1597 }
f3078f07 1598
56d061c5
SC
1599 se = getservbyname(port, protocol);
1600 if (!se)
1601 {
f3078f07
DS
1602 // the cast to int suppresses compiler warnings
1603 // about subscript having the type char
56d061c5
SC
1604 if (isdigit((int)port[0]))
1605 {
1606 int port_int;
1607
1608 port_int = atoi(port);
1609 addr = (struct sockaddr_in *)address->m_addr;
1610 addr->sin_port = htons(port_int);
1611 return GSOCK_NOERROR;
1612 }
1613
1614 address->m_error = GSOCK_INVPORT;
1615 return GSOCK_INVPORT;
1616 }
1617
1618 addr = (struct sockaddr_in *)address->m_addr;
1619 addr->sin_port = se->s_port;
1620
1621 return GSOCK_NOERROR;
1622}
1623
1624GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1625{
1626 struct sockaddr_in *addr;
1627
f3078f07
DS
1628 assert( address != NULL );
1629 CHECK_ADDRESS( address, INET );
1630
56d061c5
SC
1631 addr = (struct sockaddr_in *)address->m_addr;
1632 addr->sin_port = htons(port);
1633
1634 return GSOCK_NOERROR;
1635}
1636
1637GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1638{
1639 struct hostent *he;
1640 char *addr_buf;
1641 struct sockaddr_in *addr;
1642
f3078f07
DS
1643 assert( address != NULL );
1644 CHECK_ADDRESS( address, INET );
56d061c5
SC
1645
1646 addr = (struct sockaddr_in *)address->m_addr;
1647 addr_buf = (char *)&(addr->sin_addr);
1648
1649 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1650 if (he == NULL)
1651 {
1652 address->m_error = GSOCK_NOHOST;
1653 return GSOCK_NOHOST;
1654 }
1655
1656 strncpy(hostname, he->h_name, sbuf);
1657
1658 return GSOCK_NOERROR;
1659}
1660
1661unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1662{
1663 struct sockaddr_in *addr;
1664
f3078f07
DS
1665 assert( address != NULL );
1666 CHECK_ADDRESS_RETVAL( address, INET, 0 );
56d061c5
SC
1667
1668 addr = (struct sockaddr_in *)address->m_addr;
1669
1670 return ntohl(addr->sin_addr.s_addr) ;
1671}
1672
1673unsigned short GAddress_INET_GetPort(GAddress *address)
1674{
1675 struct sockaddr_in *addr;
1676
f3078f07
DS
1677 assert( address != NULL );
1678 CHECK_ADDRESS_RETVAL( address, INET, 0 );
56d061c5
SC
1679
1680 addr = (struct sockaddr_in *)address->m_addr;
f3078f07 1681
56d061c5
SC
1682 return ntohs(addr->sin_port);
1683}
1684
1685/*
1686 * -------------------------------------------------------------------------
1687 * Unix address family
1688 * -------------------------------------------------------------------------
1689 */
1690
1691GSocketError _GAddress_Init_UNIX(GAddress *address)
1692{
1693 address->m_len = sizeof(struct sockaddr_un);
1694 address->m_addr = (struct sockaddr *)malloc(address->m_len);
1695 if (address->m_addr == NULL)
1696 {
1697 address->m_error = GSOCK_MEMERR;
1698 return GSOCK_MEMERR;
1699 }
1700
1701 address->m_family = GSOCK_UNIX;
1702 address->m_realfamily = PF_UNIX;
1703 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
1704 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
1705
1706 return GSOCK_NOERROR;
1707}
1708
1709#define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0]))
1710
1711GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1712{
1713 struct sockaddr_un *addr;
1714
f3078f07
DS
1715 assert( address != NULL );
1716 CHECK_ADDRESS( address, UNIX );
56d061c5
SC
1717
1718 addr = ((struct sockaddr_un *)address->m_addr);
1719 strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);
1720 addr->sun_path[UNIX_SOCK_PATHLEN - 1] = '\0';
1721
1722 return GSOCK_NOERROR;
1723}
1724
1725GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1726{
1727 struct sockaddr_un *addr;
1728
f3078f07
DS
1729 assert( address != NULL );
1730 CHECK_ADDRESS( address, UNIX );
56d061c5
SC
1731
1732 addr = (struct sockaddr_un *)address->m_addr;
1733
1734 strncpy(path, addr->sun_path, sbuf);
1735
1736 return GSOCK_NOERROR;
1737}
1738
1739/* Address handling */
1740
1741/* GSocket_SetLocal:
1742 * GSocket_GetLocal:
1743 * GSocket_SetPeer:
1744 * GSocket_GetPeer:
1745 * Set or get the local or peer address for this socket. The 'set'
1746 * functions return GSOCK_NOERROR on success, an error code otherwise.
1747 * The 'get' functions return a pointer to a GAddress object on success,
1748 * or NULL otherwise, in which case they set the error code of the
1749 * corresponding GSocket.
1750 *
1751 * Error codes:
1752 * GSOCK_INVSOCK - the socket is not valid.
1753 * GSOCK_INVADDR - the address is not valid.
1754 */
f3078f07 1755
56d061c5
SC
1756GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
1757{
f3078f07 1758 assert( socket != NULL );
56d061c5 1759
f3078f07 1760 // the socket must be initialized, or it must be a server
56d061c5
SC
1761 if ((socket->m_fd != INVALID_SOCKET && !socket->m_server))
1762 {
1763 socket->m_error = GSOCK_INVSOCK;
1764 return GSOCK_INVSOCK;
1765 }
1766
f3078f07 1767 // check address
56d061c5
SC
1768 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
1769 {
1770 socket->m_error = GSOCK_INVADDR;
1771 return GSOCK_INVADDR;
1772 }
1773
1774 if (socket->m_local)
1775 GAddress_destroy(socket->m_local);
1776
1777 socket->m_local = GAddress_copy(address);
1778
1779 return GSOCK_NOERROR;
1780}
1781
1782GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
1783{
1784 assert(socket != NULL);
1785
f3078f07 1786 // check address
56d061c5
SC
1787 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
1788 {
1789 socket->m_error = GSOCK_INVADDR;
1790 return GSOCK_INVADDR;
1791 }
1792
1793 if (socket->m_peer)
1794 GAddress_destroy(socket->m_peer);
1795
1796 socket->m_peer = GAddress_copy(address);
1797
1798 return GSOCK_NOERROR;
1799}
1800
1801GAddress *GSocket_GetLocal(GSocket *socket)
1802{
1803 GAddress *address;
1804 struct sockaddr addr;
1805 socklen_t size = sizeof(addr);
1806 GSocketError err;
1807
f3078f07 1808 assert( socket != NULL );
56d061c5 1809
f3078f07 1810 // try to get it from the m_local var first
56d061c5
SC
1811 if (socket->m_local)
1812 return GAddress_copy(socket->m_local);
1813
f3078f07 1814 // else, if the socket is initialized, try getsockname
56d061c5
SC
1815 if (socket->m_fd == INVALID_SOCKET)
1816 {
1817 socket->m_error = GSOCK_INVSOCK;
1818 return NULL;
1819 }
1820
1821 if (getsockname(socket->m_fd, &addr, (socklen_t *) &size) < 0)
1822 {
1823 socket->m_error = GSOCK_IOERR;
1824 return NULL;
1825 }
1826
f3078f07 1827 // got a valid address from getsockname, create a GAddress object
56d061c5
SC
1828 address = GAddress_new();
1829 if (address == NULL)
1830 {
1831 socket->m_error = GSOCK_MEMERR;
1832 return NULL;
1833 }
1834
1835 err = _GAddress_translate_from(address, &addr, size);
1836 if (err != GSOCK_NOERROR)
1837 {
1838 GAddress_destroy(address);
1839 socket->m_error = err;
1840 return NULL;
1841 }
1842
1843 return address;
1844}
1845
1846GAddress *GSocket_GetPeer(GSocket *socket)
1847{
1848 assert(socket != NULL);
1849
f3078f07 1850 // try to get it from the m_peer var
56d061c5
SC
1851 if (socket->m_peer)
1852 return GAddress_copy(socket->m_peer);
1853
1854 return NULL;
1855}
1856
56d061c5
SC
1857
1858GSocket *GSocket_new(void)
1859{
1860 GSocket *socket;
1861 socket = (GSocket *)malloc(sizeof(GSocket));
1862
1863 if (socket == NULL)
1864 return NULL;
f3078f07 1865
56d061c5
SC
1866 socket->m_fd = INVALID_SOCKET;
1867
1868 for (int i=0;i<GSOCK_MAX_EVENT;i++)
1869 {
f3078f07 1870 socket->m_cbacks[i] = NULL;
56d061c5 1871 }
f3078f07 1872
56d061c5
SC
1873 socket->m_detected = 0;
1874
1875 socket->m_local = NULL;
1876 socket->m_peer = NULL;
1877 socket->m_error = GSOCK_NOERROR;
1878
f3078f07
DS
1879 socket->m_non_blocking = false ;
1880 socket->m_stream = true;
1881// socket->m_oriented = true;
1882 socket->m_server = false;
1883 socket->m_establishing = false;
1884 socket->m_timeout = 10 * 60 * 1000;
1885 // 10 minutes * 60 sec * 1000 millisec
1886
56d061c5
SC
1887 socket->m_cfSocket = NULL ;
1888 socket->m_runLoopSource = NULL ;
1889 socket->m_readStream = NULL;
1890 socket->m_writeStream = NULL;
f3078f07 1891
56d061c5
SC
1892 return socket ;
1893}
1894
1895void GSocket_close(GSocket *socket)
1896{
f3078f07 1897 if ( socket->m_cfSocket != NULL )
56d061c5 1898 {
f3078f07
DS
1899 if ( socket->m_readStream )
1900 {
1901 CFReadStreamClose(socket->m_readStream);
1902 CFRelease( socket->m_readStream ) ;
1903 socket->m_readStream = NULL ;
1904 }
56d061c5 1905
f3078f07
DS
1906 if ( socket->m_writeStream )
1907 {
1908 CFWriteStreamClose(socket->m_writeStream);
1909 CFRelease( socket->m_writeStream ) ;
1910 socket->m_writeStream = NULL ;
1911 }
1912
1913 CFSocketInvalidate( socket->m_cfSocket ) ;
1914 CFRelease( socket->m_cfSocket ) ;
1915 socket->m_cfSocket = NULL ;
1916 socket->m_fd = INVALID_SOCKET ;
1917 }
56d061c5
SC
1918}
1919
1920void GSocket_Shutdown(GSocket *socket)
1921{
f3078f07 1922 GSocket_close( socket );
56d061c5 1923
f3078f07
DS
1924 // Disable GUI callbacks
1925 for (int evt = 0; evt < GSOCK_MAX_EVENT; evt++)
1926 socket->m_cbacks[evt] = NULL;
56d061c5 1927
f3078f07 1928 socket->m_detected = GSOCK_LOST_FLAG;
56d061c5
SC
1929}
1930
1931void GSocket_destroy(GSocket *socket)
1932{
f3078f07 1933 assert( socket != NULL );
56d061c5 1934
f3078f07 1935 // Check that the socket is really shut down
56d061c5
SC
1936 if (socket->m_fd != INVALID_SOCKET)
1937 GSocket_Shutdown(socket);
1938
f3078f07 1939 // Destroy private addresses
56d061c5
SC
1940 if (socket->m_local)
1941 GAddress_destroy(socket->m_local);
1942
1943 if (socket->m_peer)
1944 GAddress_destroy(socket->m_peer);
1945
f3078f07 1946 // Destroy the socket itself
56d061c5
SC
1947 free(socket);
1948}
1949
1950GSocketError GSocket_Connect(GSocket *socket, GSocketStream stream)
1951{
f3078f07 1952 assert( socket != NULL );
56d061c5
SC
1953
1954 if (socket->m_fd != INVALID_SOCKET)
1955 {
1956 socket->m_error = GSOCK_INVSOCK;
1957 return GSOCK_INVSOCK;
1958 }
1959
1960 if (!socket->m_peer)
1961 {
1962 socket->m_error = GSOCK_INVADDR;
1963 return GSOCK_INVADDR;
1964 }
1965
f3078f07 1966 // Streamed or dgram socket?
56d061c5 1967 socket->m_stream = (stream == GSOCK_STREAMED);
f3078f07
DS
1968 socket->m_oriented = true;
1969 socket->m_server = false;
1970 socket->m_establishing = false;
56d061c5
SC
1971
1972 GSocketError returnErr = GSOCK_NOERROR ;
1973 CFSocketError err ;
f3078f07 1974
56d061c5
SC
1975 CFAllocatorRef alloc = kCFAllocatorDefault ;
1976 CFSocketContext ctx ;
1977 memset( &ctx , 0 , sizeof( ctx ) ) ;
1978 ctx.info = socket ;
1979 socket->m_cfSocket = CFSocketCreate( alloc , socket->m_peer->m_realfamily ,
f3078f07 1980 stream == GSOCK_STREAMED ? SOCK_STREAM : SOCK_DGRAM , 0 ,
56d061c5
SC
1981 kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack , wxMacCFSocketCallback , &ctx ) ;
1982 _GSocket_Enable(socket, GSOCK_CONNECTION);
56d061c5 1983
f3078f07
DS
1984 socket->m_fd = CFSocketGetNative( socket->m_cfSocket ) ;
1985
1986 CFStreamCreatePairWithSocket ( alloc , socket->m_fd , &socket->m_readStream , &socket->m_writeStream );
1987 if ((socket->m_readStream == NULL) || (socket->m_writeStream == NULL))
56d061c5
SC
1988 {
1989 GSocket_close(socket);
1990 socket->m_error = GSOCK_IOERR;
1991 return GSOCK_IOERR;
1992 }
f3078f07 1993
56d061c5
SC
1994 if ( !CFReadStreamOpen( socket->m_readStream ) || !CFWriteStreamOpen( socket->m_writeStream ) )
1995 {
1996 GSocket_close(socket);
1997 socket->m_error = GSOCK_IOERR;
1998 return GSOCK_IOERR;
1999 }
f3078f07 2000
56d061c5
SC
2001 CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource(alloc , socket->m_cfSocket , 0);
2002 CFRunLoopAddSource(CFRunLoopGetCurrent() , rls, kCFRunLoopCommonModes);
2003 CFRelease(rls);
f3078f07 2004
56d061c5
SC
2005 CFDataRef address = CFDataCreateWithBytesNoCopy(alloc, (const UInt8*) socket->m_peer->m_addr, socket->m_peer->m_len , kCFAllocatorNull);
2006 if ( !address )
2007 return GSOCK_MEMERR ;
f3078f07 2008
56d061c5
SC
2009 err = CFSocketConnectToAddress( socket->m_cfSocket , address, socket->m_non_blocking ? -1 : socket->m_timeout / 1000 ) ;
2010 CFRelease(address);
f3078f07 2011
56d061c5
SC
2012 if (err != kCFSocketSuccess)
2013 {
2014 if ( err == kCFSocketTimeout )
f3078f07 2015 {
56d061c5
SC
2016 GSocket_close(socket);
2017 socket->m_error = GSOCK_TIMEDOUT ;
2018 return GSOCK_TIMEDOUT ;
2019 }
f3078f07 2020
56d061c5
SC
2021 // we don't know whether a connect in progress will be issued like this
2022 if ( err != kCFSocketTimeout && socket->m_non_blocking )
2023 {
f3078f07 2024 socket->m_establishing = true;
56d061c5
SC
2025 socket->m_error = GSOCK_WOULDBLOCK;
2026 return GSOCK_WOULDBLOCK;
2027 }
f3078f07 2028
56d061c5
SC
2029 GSocket_close(socket);
2030 socket->m_error = GSOCK_IOERR;
2031 return GSOCK_IOERR;
2032 }
2033
2034 return GSOCK_NOERROR;
2035}
2036
2037/* Flags */
2038
2039/* GSocket_SetNonBlocking:
f3078f07
DS
2040 * Sets the socket to non-blocking mode.
2041 * All IO calls will return immediately.
56d061c5
SC
2042 */
2043void GSocket_SetNonBlocking(GSocket *socket, int non_block)
2044{
f3078f07 2045 assert( socket != NULL );
56d061c5
SC
2046
2047// GSocket_Debug( ("GSocket_SetNonBlocking: %d\n", (int)non_block) );
2048
2049 socket->m_non_blocking = non_block;
2050}
2051
f3078f07
DS
2052/*
2053 * GSocket_SetTimeout:
56d061c5
SC
2054 * Sets the timeout for blocking calls. Time is expressed in
2055 * milliseconds.
2056 */
2057void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
2058{
f3078f07 2059 assert( socket != NULL );
56d061c5
SC
2060
2061 socket->m_timeout = millisec;
2062}
2063
2064/* GSocket_GetError:
3103e8a9 2065 * Returns the last error which occurred for this socket. Note that successful
56d061c5
SC
2066 * operations do not clear this back to GSOCK_NOERROR, so use it only
2067 * after an error.
2068 */
2069GSocketError GSocket_GetError(GSocket *socket)
2070{
f3078f07 2071 assert( socket != NULL );
56d061c5
SC
2072
2073 return socket->m_error;
2074}
2075
2076/* Callbacks */
2077
2078/* GSOCK_INPUT:
2079 * There is data to be read in the input buffer. If, after a read
2080 * operation, there is still data available, the callback function will
2081 * be called again.
2082 * GSOCK_OUTPUT:
f3078f07 2083 * The socket is available for writing. That is, the next write call
56d061c5
SC
2084 * won't block. This event is generated only once, when the connection is
2085 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
2086 * when the output buffer empties again. This means that the app should
2087 * assume that it can write since the first OUTPUT event, and no more
2088 * OUTPUT events will be generated unless an error occurs.
2089 * GSOCK_CONNECTION:
3103e8a9 2090 * Connection successfully established, for client sockets, or incoming
56d061c5
SC
2091 * client connection, for server sockets. Wait for this event (also watch
2092 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
2093 * GSOCK_LOST:
2094 * The connection is lost (or a connection request failed); this could
2095 * be due to a failure, or due to the peer closing it gracefully.
2096 */
2097
2098/* GSocket_SetCallback:
2099 * Enables the callbacks specified by 'flags'. Note that 'flags'
2100 * may be a combination of flags OR'ed toghether, so the same
2101 * callback function can be made to accept different events.
2102 * The callback function must have the following prototype:
2103 *
2104 * void function(GSocket *socket, GSocketEvent event, char *cdata)
2105 */
2106void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
2107 GSocketCallback callback, char *cdata)
2108{
2109 int count;
2110
f3078f07 2111 assert( socket != NULL );
56d061c5
SC
2112
2113 for (count = 0; count < GSOCK_MAX_EVENT; count++)
2114 {
2115 if ((flags & (1 << count)) != 0)
2116 {
2117 socket->m_cbacks[count] = callback;
2118 socket->m_data[count] = cdata;
2119 }
2120 }
2121}
2122
2123/* GSocket_UnsetCallback:
2124 * Disables all callbacks specified by 'flags', which may be a
2125 * combination of flags OR'ed toghether.
2126 */
2127void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
2128{
2129 int count;
2130
2131 assert(socket != NULL);
2132
2133 for (count = 0; count < GSOCK_MAX_EVENT; count++)
2134 {
2135 if ((flags & (1 << count)) != 0)
2136 {
2137 socket->m_cbacks[count] = NULL;
2138 socket->m_data[count] = NULL;
2139 }
2140 }
2141}
2142
2143
2144#define CALL_CALLBACK(socket, event) { \
2145 _GSocket_Disable(socket, event); \
2146 if (socket->m_cbacks[event]) \
2147 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
2148}
2149
2150void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
2151{
2152 int c;
2153 switch (event)
2154 {
2155 case GSOCK_CONNECTION:
f3078f07 2156 if (socket->m_server)
56d061c5
SC
2157 c = kCFSocketReadCallBack;
2158 else
2159 c = kCFSocketConnectCallBack;
2160 break;
f3078f07 2161
56d061c5
SC
2162 case GSOCK_LOST:
2163 case GSOCK_INPUT:
2164 c = kCFSocketReadCallBack;
2165 break;
f3078f07 2166
56d061c5
SC
2167 case GSOCK_OUTPUT:
2168 c = kCFSocketWriteCallBack;
2169 break;
f3078f07 2170
56d061c5
SC
2171 default:
2172 c = 0;
2173 }
f3078f07 2174
56d061c5
SC
2175 CFSocketEnableCallBacks(socket->m_cfSocket, c);
2176}
2177
2178void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
2179{
2180 int c;
2181 switch (event)
2182 {
2183 case GSOCK_CONNECTION:
f3078f07 2184 if (socket->m_server)
56d061c5
SC
2185 c = kCFSocketReadCallBack;
2186 else
2187 c = kCFSocketConnectCallBack;
2188 break;
f3078f07 2189
56d061c5
SC
2190 case GSOCK_LOST:
2191 case GSOCK_INPUT:
2192 c = kCFSocketReadCallBack;
2193 break;
f3078f07 2194
56d061c5
SC
2195 case GSOCK_OUTPUT:
2196 c = kCFSocketWriteCallBack;
2197 break;
f3078f07 2198
56d061c5
SC
2199 default:
2200 c = 0;
f3078f07 2201 break;
56d061c5 2202 }
f3078f07 2203
56d061c5
SC
2204 CFSocketDisableCallBacks(socket->m_cfSocket, c);
2205}
2206
2207void _GSocket_Enable(GSocket *socket, GSocketEvent event)
2208{
2209 socket->m_detected &= ~(1 << event);
2210 _GSocket_Install_Callback(socket, event);
2211}
2212
2213void _GSocket_Disable(GSocket *socket, GSocketEvent event)
2214{
2215 socket->m_detected |= (1 << event);
2216 _GSocket_Uninstall_Callback(socket, event);
2217}
2218
2219void wxMacCFSocketCallback(CFSocketRef s, CFSocketCallBackType callbackType,
2220 CFDataRef address, const void* data, void* info)
2221{
2222 GSocket* socket = (GSocket*)info;
2223
2224 switch (callbackType)
2225 {
2226 case kCFSocketConnectCallBack:
2227 if ( data )
2228 {
2229 SInt32 error = *((SInt32*)data) ;
2230 CALL_CALLBACK( socket , GSOCK_LOST ) ;
2231 GSocket_Shutdown(socket);
2232 }
2233 else
2234 {
2235 CALL_CALLBACK( socket , GSOCK_CONNECTION ) ;
2236 }
2237 break;
f3078f07 2238
56d061c5
SC
2239 case kCFSocketReadCallBack:
2240 CALL_CALLBACK( socket , GSOCK_INPUT ) ;
2241 break;
f3078f07 2242
56d061c5
SC
2243 case kCFSocketWriteCallBack:
2244 CALL_CALLBACK( socket , GSOCK_OUTPUT ) ;
2245 break;
f3078f07 2246
56d061c5 2247 default:
f3078f07 2248 break; // We shouldn't get here.
56d061c5
SC
2249 }
2250}
2251
2252int GSocket_Read(GSocket *socket, char *buffer, int size)
2253{
2254 int ret = 0 ;
2255
2256 assert(socket != NULL);
2257 // if ( !CFReadStreamHasBytesAvailable() )
2258 ret = CFReadStreamRead( socket->m_readStream , (UInt8*) buffer , size ) ;
2259
2260 return ret;
2261}
2262
2263int GSocket_Write(GSocket *socket, const char *buffer, int size)
f3078f07 2264{
56d061c5
SC
2265 int ret;
2266
2267 assert(socket != NULL);
2268 ret = CFWriteStreamWrite( socket->m_writeStream , (UInt8*) buffer , size ) ;
f3078f07 2269
56d061c5
SC
2270 return ret;
2271}
2272
2273GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
2274{
f3078f07
DS
2275 assert( socket != NULL );
2276
56d061c5
SC
2277 return flags & socket->m_detected;
2278}
2279
2280// ==========================================================================
2281// wxSocketModule
2282// ==========================================================================
2283
2284class wxSocketModule : public wxModule
2285{
2286public:
2287 virtual bool OnInit()
2288 {
2289 // wxSocketBase will call GSocket_Init() itself when/if needed
f3078f07 2290 return true;
56d061c5
SC
2291 }
2292
2293 virtual void OnExit()
2294 {
2295 if ( wxSocketBase::IsInitialized() )
2296 wxSocketBase::Shutdown();
2297 }
2298
2299private:
2300 DECLARE_DYNAMIC_CLASS(wxSocketModule)
2301};
2302
2303IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
2304
2305#endif
2306 // wxUSE_SOCKETS