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