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