]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
Implemented wxStatusBar::Push/PopStatusText.
[wxWidgets.git] / src / common / socket.cpp
CommitLineData
56d8adc0 1/////////////////////////////////////////////////////////////////////////////
f4ada568
GL
2// Name: socket.cpp
3// Purpose: Socket handler classes
56d8adc0 4// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
f4ada568 5// Created: April 1997
d3ea6527
GRG
6// Copyright: (C) 1999-1997, Guilhem Lavaux
7// (C) 2000-1999, Guillermo Rodriguez Garcia
f4ada568
GL
8// RCS_ID: $Id$
9// License: see wxWindows license
56d8adc0
GRG
10/////////////////////////////////////////////////////////////////////////////
11
bffc1eaa
GRG
12// ==========================================================================
13// Declarations
14// ==========================================================================
15
384b4373 16#ifdef __GNUG__
f4ada568 17#pragma implementation "socket.h"
f4ada568
GL
18#endif
19
fcc6dddd
JS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24#pragma hdrstop
25#endif
26
35a4dab7
GL
27#if wxUSE_SOCKETS
28
dc5c1114 29#include "wx/app.h"
56d8adc0
GRG
30#include "wx/defs.h"
31#include "wx/object.h"
32#include "wx/string.h"
33#include "wx/timer.h"
34#include "wx/utils.h"
35#include "wx/module.h"
36#include "wx/log.h"
58c837a4 37#include "wx/intl.h"
f187448d 38#include "wx/event.h"
52a07708
VZ
39
40#if wxUSE_GUI
f187448d 41 #include "wx/gdicmn.h" // for wxPendingDelete
52a07708 42#endif // wxUSE_GUI
81b92e17 43
56d8adc0
GRG
44#include "wx/sckaddr.h"
45#include "wx/socket.h"
3b4183d8 46
bffc1eaa
GRG
47// --------------------------------------------------------------------------
48// macros and constants
49// --------------------------------------------------------------------------
ef57d866 50
dc5c1114
GRG
51// discard buffer
52#define MAX_DISCARD_SIZE (10 * 1024)
96db102a 53
2f10f423
VZ
54// what to do within waits: in wxBase we don't do anything as we don't have
55// the event loop anyhow (for now). In GUI apps we have 2 cases: from the main
56// thread itself we have to call wxYield() to let the events (including the
57// GUI events and the low-level (not wxWindows) events from GSocket) be
58// processed. From another thread it is enough to just call wxThread::Yield()
59// which will give away the rest of our time slice: the explanation is that
60// the events will be processed by the main thread anyhow, without calling
61// wxYield(), but we don't want to eat the CPU time uselessly while sitting
62// in the loop waiting for the data
f187448d 63#if wxUSE_GUI
2f10f423
VZ
64 #if wxUSE_THREADS
65 #define PROCESS_EVENTS() \
66 { \
67 if ( wxThread::IsMain() ) \
68 wxYield(); \
69 else \
70 wxThread::Yield(); \
71 }
72 #else // !wxUSE_THREADS
73 #define PROCESS_EVENTS() wxYield()
74 #endif // wxUSE_THREADS/!wxUSE_THREADS
75#else // !wxUSE_GUI
76 #define PROCESS_EVENTS()
77#endif // wxUSE_GUI/!wxUSE_GUI
96db102a 78
ef57d866 79// --------------------------------------------------------------------------
bffc1eaa 80// wxWin macros
ef57d866 81// --------------------------------------------------------------------------
81b92e17 82
a737331d
GL
83IMPLEMENT_CLASS(wxSocketBase, wxObject)
84IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
85IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
dc5c1114 86IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
a737331d 87IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
f4ada568 88
bffc1eaa
GRG
89// --------------------------------------------------------------------------
90// private classes
91// --------------------------------------------------------------------------
92
56d8adc0
GRG
93class wxSocketState : public wxObject
94{
a324a7bc 95public:
71622a7a 96 wxSocketFlags m_flags;
bffc1eaa
GRG
97 wxSocketEventFlags m_eventmask;
98 bool m_notify;
99 void *m_clientData;
100#if WXWIN_COMPATIBILITY
81b92e17
GRG
101 wxSocketBase::wxSockCbk m_cbk;
102 char *m_cdata;
bffc1eaa 103#endif // WXWIN_COMPATIBILITY
a324a7bc
GL
104
105public:
106 wxSocketState() : wxObject() {}
107};
108
ef57d866
GRG
109// ==========================================================================
110// wxSocketBase
111// ==========================================================================
112
6c0d0845
VZ
113// --------------------------------------------------------------------------
114// Initialization and shutdown
115// --------------------------------------------------------------------------
116
117// FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
118// to m_countInit with a crit section
119size_t wxSocketBase::m_countInit = 0;
120
121bool wxSocketBase::IsInitialized()
122{
123 return m_countInit > 0;
124}
125
126bool wxSocketBase::Initialize()
127{
128 if ( !m_countInit++ )
129 {
130 if ( !GSocket_Init() )
131 {
132 m_countInit--;
133
134 return FALSE;
135 }
136 }
137
138 return TRUE;
139}
140
141void wxSocketBase::Shutdown()
142{
143 // we should be initialized
144 wxASSERT_MSG( m_countInit, _T("extra call to Shutdown()") );
145 if ( !--m_countInit )
146 {
147 GSocket_Cleanup();
148 }
149}
150
ef57d866
GRG
151// --------------------------------------------------------------------------
152// Ctor and dtor
153// --------------------------------------------------------------------------
56d8adc0 154
71622a7a 155void wxSocketBase::Init()
f4ada568 156{
71622a7a
GRG
157 m_socket = NULL;
158 m_type = wxSOCKET_UNINIT;
159
160 // state
161 m_flags = 0;
162 m_connected =
163 m_establishing =
164 m_reading =
165 m_writing =
166 m_error = FALSE;
167 m_lcount = 0;
168 m_timeout = 600;
169 m_beingDeleted = FALSE;
170
171 // pushback buffer
172 m_unread = NULL;
173 m_unrd_size = 0;
174 m_unrd_cur = 0;
175
176 // events
71622a7a 177 m_id = -1;
f187448d
GRG
178 m_handler = NULL;
179 m_clientData = NULL;
bffc1eaa
GRG
180 m_notify = FALSE;
181 m_eventmask = 0;
182#if WXWIN_COMPATIBILITY
71622a7a
GRG
183 m_cbk = NULL;
184 m_cdata = NULL;
bffc1eaa 185#endif // WXWIN_COMPATIBILITY
6c0d0845
VZ
186
187 if ( !IsInitialized() )
188 {
189 // this Initialize() will be undone by wxSocketModule::OnExit(), all the
190 // other calls to it should be matched by a call to Shutdown()
191 Initialize();
192 }
f4ada568
GL
193}
194
f187448d
GRG
195wxSocketBase::wxSocketBase()
196{
197 Init();
198}
71622a7a
GRG
199
200wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
f4ada568 201{
71622a7a
GRG
202 Init();
203
204 m_flags = flags;
205 m_type = type;
f4ada568
GL
206}
207
f4ada568
GL
208wxSocketBase::~wxSocketBase()
209{
9181a383
GRG
210 // Just in case the app called Destroy() *and* then deleted
211 // the socket immediately: don't leave dangling pointers.
212#if wxUSE_GUI
213 wxPendingDelete.DeleteObject(this);
214#endif
a737331d 215
56d8adc0 216 // Shutdown and close the socket
9181a383
GRG
217 if (!m_beingDeleted)
218 Close();
f4ada568 219
56d8adc0 220 // Destroy the GSocket object
a324a7bc
GL
221 if (m_socket)
222 GSocket_destroy(m_socket);
9181a383
GRG
223
224 // Free the pushback buffer
225 if (m_unread)
226 free(m_unread);
f4ada568
GL
227}
228
ef57d866
GRG
229bool wxSocketBase::Destroy()
230{
231 // Delayed destruction: the socket will be deleted during the next
232 // idle loop iteration. This ensures that all pending events have
233 // been processed.
ef57d866 234 m_beingDeleted = TRUE;
9181a383
GRG
235
236 // Shutdown and close the socket
ef57d866
GRG
237 Close();
238
bffc1eaa
GRG
239 // Supress events from now on
240 Notify(FALSE);
241
9181a383 242#if wxUSE_GUI
bffc1eaa
GRG
243 if ( !wxPendingDelete.Member(this) )
244 wxPendingDelete.Append(this);
9181a383
GRG
245#else
246 delete this;
247#endif
ef57d866
GRG
248
249 return TRUE;
250}
9181a383 251
ef57d866 252// --------------------------------------------------------------------------
bffc1eaa 253// Basic IO calls
ef57d866
GRG
254// --------------------------------------------------------------------------
255
256// The following IO operations update m_error and m_lcount:
257// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
258//
259// TODO: Should Connect, Accept and AcceptWith update m_error?
260
f4ada568
GL
261bool wxSocketBase::Close()
262{
81b92e17 263 // Interrupt pending waits
02d15cad 264 InterruptWait();
81b92e17 265
31528cd3 266 if (m_socket)
8c14576d 267 {
56d8adc0
GRG
268 // Disable callbacks
269 GSocket_UnsetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
270 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
f4ada568 271
56d8adc0 272 // Shutdown the connection
a324a7bc 273 GSocket_Shutdown(m_socket);
f4ada568
GL
274 }
275
ef57d866 276 m_connected = FALSE;
04e1eb03 277 m_establishing = FALSE;
f4ada568
GL
278 return TRUE;
279}
280
f187448d 281wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 282{
96db102a
GRG
283 // Mask read events
284 m_reading = TRUE;
a324a7bc 285
96db102a 286 m_lcount = _Read(buffer, nbytes);
17aa2bec 287
d3ea6527
GRG
288 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
289 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
290 m_error = (m_lcount != nbytes);
291 else
292 m_error = (m_lcount == 0);
f4ada568 293
dc5c1114 294 // Allow read events from now on
96db102a 295 m_reading = FALSE;
17aa2bec 296
96db102a
GRG
297 return *this;
298}
299
f187448d 300wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
96db102a
GRG
301{
302 int total;
303 int ret = 1;
a324a7bc 304
04e1eb03 305 // Try the pushback buffer first
96db102a
GRG
306 total = GetPushback(buffer, nbytes, FALSE);
307 nbytes -= total;
f187448d 308 buffer = (char *)buffer + total;
96db102a 309
5f3629ba
GRG
310 // Return now in one of the following cases:
311 // - the socket is invalid,
312 // - we got all the data,
313 // - we got *some* data and we are not using wxSOCKET_WAITALL.
314 if ( !m_socket ||
315 !nbytes ||
316 ((total != 0) && !(m_flags & wxSOCKET_WAITALL)) )
96db102a 317 return total;
f4ada568 318
af2fd961 319 // Possible combinations (they are checked in this order)
81b92e17 320 // wxSOCKET_NOWAIT
5c9eff30 321 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
81b92e17
GRG
322 // wxSOCKET_BLOCK
323 // wxSOCKET_NONE
af2fd961 324 //
81b92e17 325 if (m_flags & wxSOCKET_NOWAIT)
af2fd961 326 {
5c9eff30 327 GSocket_SetNonBlocking(m_socket, 1);
f187448d 328 ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
5c9eff30 329 GSocket_SetNonBlocking(m_socket, 0);
af2fd961
GRG
330
331 if (ret > 0)
96db102a 332 total += ret;
af2fd961 333 }
5c9eff30 334 else
56d8adc0 335 {
5c9eff30
GRG
336 bool more = TRUE;
337
338 while (more)
56d8adc0 339 {
5c9eff30
GRG
340 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
341 break;
81b92e17 342
f187448d 343 ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
a324a7bc 344
81b92e17
GRG
345 if (ret > 0)
346 {
347 total += ret;
81b92e17 348 nbytes -= ret;
f187448d 349 buffer = (char *)buffer + ret;
81b92e17 350 }
a324a7bc 351
5c9eff30
GRG
352 // If we got here and wxSOCKET_WAITALL is not set, we can leave
353 // now. Otherwise, wait until we recv all the data or until there
354 // is an error.
355 //
356 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
81b92e17 357 }
a324a7bc 358 }
f4ada568 359
96db102a 360 return total;
f4ada568
GL
361}
362
f187448d 363wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
062c4861 364{
96db102a
GRG
365 wxUint32 len, len2, sig, total;
366 bool error;
17aa2bec 367 int old_flags;
17aa2bec
GRG
368 struct
369 {
96db102a
GRG
370 unsigned char sig[4];
371 unsigned char len[4];
062c4861
GL
372 } msg;
373
96db102a
GRG
374 // Mask read events
375 m_reading = TRUE;
062c4861 376
96db102a
GRG
377 total = 0;
378 error = TRUE;
17aa2bec 379 old_flags = m_flags;
81b92e17 380 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
17aa2bec 381
f187448d 382 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
96db102a 383 goto exit;
062c4861 384
f187448d 385 sig = (wxUint32)msg.sig[0];
96db102a
GRG
386 sig |= (wxUint32)(msg.sig[1] << 8);
387 sig |= (wxUint32)(msg.sig[2] << 16);
388 sig |= (wxUint32)(msg.sig[3] << 24);
062c4861
GL
389
390 if (sig != 0xfeeddead)
17aa2bec 391 {
5c9eff30 392 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
96db102a 393 goto exit;
17aa2bec
GRG
394 }
395
96db102a
GRG
396 len = (wxUint32)msg.len[0];
397 len |= (wxUint32)(msg.len[1] << 8);
398 len |= (wxUint32)(msg.len[2] << 16);
399 len |= (wxUint32)(msg.len[3] << 24);
400
17aa2bec
GRG
401 if (len > nbytes)
402 {
062c4861
GL
403 len2 = len - nbytes;
404 len = nbytes;
405 }
406 else
407 len2 = 0;
408
04e1eb03 409 // Don't attemp to read if the msg was zero bytes long.
96db102a 410 if (len)
17aa2bec 411 {
96db102a
GRG
412 total = _Read(buffer, len);
413
414 if (total != len)
415 goto exit;
17aa2bec
GRG
416 }
417 if (len2)
418 {
96db102a 419 char *discard_buffer = new char[MAX_DISCARD_SIZE];
17aa2bec
GRG
420 long discard_len;
421
96db102a 422 // NOTE: discarded bytes don't add to m_lcount.
17aa2bec
GRG
423 do
424 {
96db102a 425 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
479cd5de
VZ
426 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
427 len2 -= (wxUint32)discard_len;
17aa2bec
GRG
428 }
429 while ((discard_len > 0) && len2);
430
431 delete [] discard_buffer;
432
433 if (len2 != 0)
96db102a 434 goto exit;
17aa2bec 435 }
f187448d 436 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
96db102a 437 goto exit;
062c4861 438
96db102a
GRG
439 sig = (wxUint32)msg.sig[0];
440 sig |= (wxUint32)(msg.sig[1] << 8);
441 sig |= (wxUint32)(msg.sig[2] << 16);
442 sig |= (wxUint32)(msg.sig[3] << 24);
a324a7bc 443
062c4861 444 if (sig != 0xdeadfeed)
17aa2bec 445 {
5c9eff30 446 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
96db102a 447 goto exit;
17aa2bec 448 }
062c4861 449
96db102a
GRG
450 // everything was OK
451 error = FALSE;
452
453exit:
454 m_error = error;
455 m_lcount = total;
456 m_reading = FALSE;
17aa2bec 457 SetFlags(old_flags);
96db102a 458
062c4861
GL
459 return *this;
460}
461
f187448d 462wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
f4ada568 463{
96db102a
GRG
464 // Mask read events
465 m_reading = TRUE;
466
467 m_lcount = _Read(buffer, nbytes);
dc5c1114 468 Pushback(buffer, m_lcount);
96db102a 469
81b92e17
GRG
470 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
471 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
472 m_error = (m_lcount != nbytes);
473 else
474 m_error = (m_lcount == 0);
475
dc5c1114 476 // Allow read events again
96db102a 477 m_reading = FALSE;
f4ada568
GL
478
479 return *this;
480}
481
f187448d 482wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 483{
96db102a
GRG
484 // Mask write events
485 m_writing = TRUE;
56d8adc0 486
96db102a
GRG
487 m_lcount = _Write(buffer, nbytes);
488
81b92e17
GRG
489 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
490 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
491 m_error = (m_lcount != nbytes);
492 else
493 m_error = (m_lcount == 0);
494
dc5c1114 495 // Allow write events again
96db102a
GRG
496 m_writing = FALSE;
497
96db102a
GRG
498 return *this;
499}
500
f187448d 501wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
96db102a
GRG
502{
503 wxUint32 total = 0;
504 int ret = 1;
56d8adc0 505
5c9eff30
GRG
506 // If the socket is invalid or parameters are ill, return immediately
507 if (!m_socket || !buffer || !nbytes)
96db102a 508 return 0;
a324a7bc 509
af2fd961 510 // Possible combinations (they are checked in this order)
81b92e17 511 // wxSOCKET_NOWAIT
5c9eff30 512 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
81b92e17
GRG
513 // wxSOCKET_BLOCK
514 // wxSOCKET_NONE
af2fd961 515 //
81b92e17 516 if (m_flags & wxSOCKET_NOWAIT)
af2fd961 517 {
5c9eff30 518 GSocket_SetNonBlocking(m_socket, 1);
f187448d 519 ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
5c9eff30 520 GSocket_SetNonBlocking(m_socket, 0);
af2fd961
GRG
521
522 if (ret > 0)
96db102a 523 total = ret;
af2fd961 524 }
5c9eff30 525 else
56d8adc0 526 {
5c9eff30
GRG
527 bool more = TRUE;
528
c3e646b4 529 while (more)
56d8adc0 530 {
5c9eff30
GRG
531 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
532 break;
81b92e17 533
f187448d 534 ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
5c9eff30 535
81b92e17
GRG
536 if (ret > 0)
537 {
538 total += ret;
81b92e17 539 nbytes -= ret;
f187448d 540 buffer = (const char *)buffer + ret;
81b92e17 541 }
a324a7bc 542
5c9eff30
GRG
543 // If we got here and wxSOCKET_WAITALL is not set, we can leave
544 // now. Otherwise, wait until we send all the data or until there
545 // is an error.
546 //
547 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
81b92e17 548 }
56d8adc0 549 }
a324a7bc 550
96db102a 551 return total;
f4ada568
GL
552}
553
f187448d 554wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
062c4861 555{
96db102a
GRG
556 wxUint32 total;
557 bool error;
17aa2bec 558 int old_flags;
f187448d
GRG
559 struct
560 {
96db102a
GRG
561 unsigned char sig[4];
562 unsigned char len[4];
062c4861
GL
563 } msg;
564
96db102a
GRG
565 // Mask write events
566 m_writing = TRUE;
567
568 error = TRUE;
569 total = 0;
570 old_flags = m_flags;
81b92e17 571 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
96db102a 572
96db102a
GRG
573 msg.sig[0] = (unsigned char) 0xad;
574 msg.sig[1] = (unsigned char) 0xde;
575 msg.sig[2] = (unsigned char) 0xed;
576 msg.sig[3] = (unsigned char) 0xfe;
062c4861 577
04e1eb03
GRG
578 msg.len[0] = (unsigned char) (nbytes & 0xff);
579 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
580 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
581 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
17aa2bec 582
f187448d 583 if (_Write(&msg, sizeof(msg)) < sizeof(msg))
96db102a
GRG
584 goto exit;
585
586 total = _Write(buffer, nbytes);
587
588 if (total < nbytes)
589 goto exit;
062c4861 590
96db102a
GRG
591 msg.sig[0] = (unsigned char) 0xed;
592 msg.sig[1] = (unsigned char) 0xfe;
593 msg.sig[2] = (unsigned char) 0xad;
594 msg.sig[3] = (unsigned char) 0xde;
062c4861 595 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
062c4861 596
f187448d 597 if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
96db102a 598 goto exit;
17aa2bec 599
96db102a
GRG
600 // everything was OK
601 error = FALSE;
602
603exit:
604 m_error = error;
605 m_lcount = total;
606 m_writing = FALSE;
607
062c4861 608 return *this;
062c4861
GL
609}
610
f187448d 611wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
f4ada568 612{
56d8adc0 613 if (nbytes != 0)
96db102a 614 Pushback(buffer, nbytes);
f4ada568 615
96db102a
GRG
616 m_error = FALSE;
617 m_lcount = nbytes;
f4ada568 618
96db102a 619 return *this;
a324a7bc
GL
620}
621
96db102a 622wxSocketBase& wxSocketBase::Discard()
f4ada568 623{
96db102a 624 int old_flags;
04e1eb03
GRG
625 char *buffer = new char[MAX_DISCARD_SIZE];
626 wxUint32 ret;
17aa2bec 627 wxUint32 total = 0;
f4ada568 628
96db102a
GRG
629 // Mask read events
630 m_reading = TRUE;
631
632 old_flags = m_flags;
81b92e17 633 SetFlags(wxSOCKET_NOWAIT);
384b4373 634
04e1eb03 635 do
8c14576d 636 {
04e1eb03
GRG
637 ret = _Read(buffer, MAX_DISCARD_SIZE);
638 total += ret;
f4ada568 639 }
04e1eb03 640 while (ret == MAX_DISCARD_SIZE);
f4ada568 641
04e1eb03 642 delete[] buffer;
17aa2bec 643 m_lcount = total;
04e1eb03 644 m_error = FALSE;
17aa2bec 645
dc5c1114 646 // Allow read events again
96db102a
GRG
647 m_reading = FALSE;
648
96db102a 649 return *this;
f4ada568
GL
650}
651
ef57d866
GRG
652// --------------------------------------------------------------------------
653// Wait functions
654// --------------------------------------------------------------------------
f4ada568 655
ef57d866
GRG
656// All Wait functions poll the socket using GSocket_Select() to
657// check for the specified combination of conditions, until one
658// of these conditions become true, an error occurs, or the
659// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
660// this won't block the GUI.
f4ada568 661
bffc1eaa
GRG
662bool wxSocketBase::_Wait(long seconds,
663 long milliseconds,
d3ea6527 664 wxSocketEventFlags flags)
375abe3d 665{
56d8adc0 666 GSocketEventFlags result;
56d8adc0 667 long timeout;
375abe3d 668
81b92e17
GRG
669 // Set this to TRUE to interrupt ongoing waits
670 m_interrupt = FALSE;
671
ef57d866 672 // Check for valid socket
af2fd961
GRG
673 if (!m_socket)
674 return FALSE;
675
71622a7a 676 // Check for valid timeout value.
56d8adc0
GRG
677 if (seconds != -1)
678 timeout = seconds * 1000 + milliseconds;
679 else
680 timeout = m_timeout * 1000;
a324a7bc 681
bffc1eaa 682 // Wait in an active polling loop.
af2fd961 683 //
bffc1eaa
GRG
684 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
685 // hurt. It has to be here because the (GSocket) event might arrive
686 // a bit delayed, and it has to be in OnRequest as well because we
687 // don't know whether the Wait functions are being used.
af2fd961 688 //
96db102a 689 // Do this at least once (important if timeout == 0, when
d3ea6527 690 // we are just polling). Also, if just polling, do not yield.
ef57d866 691
71622a7a
GRG
692 wxStopWatch chrono;
693 bool done = FALSE;
694
695 while (!done)
56d8adc0 696 {
af2fd961
GRG
697 result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG);
698
af2fd961
GRG
699 // Incoming connection (server) or connection established (client)
700 if (result & GSOCK_CONNECTION_FLAG)
701 {
af2fd961
GRG
702 m_connected = TRUE;
703 m_establishing = FALSE;
704 return TRUE;
705 }
706
04e1eb03 707 // Data available or output buffer ready
81b92e17 708 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
af2fd961 709 {
81b92e17 710 return TRUE;
af2fd961
GRG
711 }
712
c0043a50
GRG
713 // Connection lost
714 if (result & GSOCK_LOST_FLAG)
715 {
ef57d866 716 m_connected = FALSE;
04e1eb03 717 m_establishing = FALSE;
378d2bd3 718 return (flags & GSOCK_LOST_FLAG) != 0;
c0043a50
GRG
719 }
720
81b92e17 721 // Wait more?
71622a7a
GRG
722 if ((!timeout) || (chrono.Time() > timeout) || (m_interrupt))
723 done = TRUE;
d3ea6527
GRG
724 else
725 PROCESS_EVENTS();
56d8adc0 726 }
f4ada568 727
af2fd961 728 return FALSE;
f4ada568 729}
f4ada568 730
a737331d 731bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 732{
d80d1aba
GRG
733 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
734 GSOCK_OUTPUT_FLAG |
735 GSOCK_CONNECTION_FLAG |
736 GSOCK_LOST_FLAG);
f4ada568 737}
f4ada568 738
a737331d 739bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 740{
ef57d866 741 // Check pushback buffer before entering _Wait
96db102a
GRG
742 if (m_unread)
743 return TRUE;
744
ef57d866
GRG
745 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
746 // _Wait becuase of the semantics of WaitForRead: a return
747 // value of TRUE means that a GSocket_Read call will return
748 // immediately, not that there is actually data to read.
749
750 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
751 GSOCK_LOST_FLAG);
f4ada568
GL
752}
753
a737331d 754bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 755{
af2fd961 756 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
a737331d 757}
f4ada568 758
a737331d
GL
759bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
760{
a324a7bc 761 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
f4ada568 762}
a737331d 763
ef57d866
GRG
764// --------------------------------------------------------------------------
765// Miscellaneous
766// --------------------------------------------------------------------------
767
768//
769// Get local or peer address
770//
771
772bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
773{
774 GAddress *peer;
775
776 if (!m_socket)
777 return FALSE;
778
779 peer = GSocket_GetPeer(m_socket);
780 addr_man.SetAddress(peer);
781 GAddress_destroy(peer);
782
783 return TRUE;
784}
785
786bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
787{
788 GAddress *local;
789
790 if (!m_socket)
791 return FALSE;
792
793 local = GSocket_GetLocal(m_socket);
794 addr_man.SetAddress(local);
795 GAddress_destroy(local);
796
797 return TRUE;
798}
799
800//
801// Save and restore socket state
802//
803
804void wxSocketBase::SaveState()
805{
806 wxSocketState *state;
807
808 state = new wxSocketState();
809
bffc1eaa
GRG
810 state->m_flags = m_flags;
811 state->m_notify = m_notify;
812 state->m_eventmask = m_eventmask;
813 state->m_clientData = m_clientData;
814#if WXWIN_COMPATIBILITY
815 state->m_cbk = m_cbk;
816 state->m_cdata = m_cdata;
817#endif // WXWIN_COMPATIBILITY
ef57d866
GRG
818
819 m_states.Append(state);
820}
821
822void wxSocketBase::RestoreState()
823{
824 wxNode *node;
825 wxSocketState *state;
826
827 node = m_states.Last();
828 if (!node)
829 return;
830
831 state = (wxSocketState *)node->Data();
832
bffc1eaa
GRG
833 m_flags = state->m_flags;
834 m_notify = state->m_notify;
835 m_eventmask = state->m_eventmask;
836 m_clientData = state->m_clientData;
837#if WXWIN_COMPATIBILITY
838 m_cbk = state->m_cbk;
839 m_cdata = state->m_cdata;
840#endif // WXWIN_COMPATIBILITY
ef57d866
GRG
841
842 delete node;
843 delete state;
844}
845
846//
847// Timeout and flags
848//
849
17aa2bec
GRG
850void wxSocketBase::SetTimeout(long seconds)
851{
852 m_timeout = seconds;
853
854 if (m_socket)
e8f4c584 855 GSocket_SetTimeout(m_socket, m_timeout * 1000);
17aa2bec
GRG
856}
857
71622a7a 858void wxSocketBase::SetFlags(wxSocketFlags flags)
f4ada568 859{
71622a7a 860 m_flags = flags;
f4ada568 861}
f0a56ab0 862
f187448d 863
ef57d866
GRG
864// --------------------------------------------------------------------------
865// Callbacks (now obsolete - use events instead)
866// --------------------------------------------------------------------------
56d8adc0 867
bffc1eaa
GRG
868#if WXWIN_COMPATIBILITY
869
56d8adc0 870wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
f4ada568 871{
56d8adc0 872 wxSockCbk old_cbk = cbk_;
f4ada568 873
56d8adc0
GRG
874 m_cbk = cbk_;
875 return old_cbk;
876}
877
878char *wxSocketBase::CallbackData(char *data)
879{
880 char *old_data = m_cdata;
881
882 m_cdata = data;
883 return old_data;
f4ada568
GL
884}
885
bffc1eaa
GRG
886#endif // WXWIN_COMPATIBILITY
887
ef57d866 888// --------------------------------------------------------------------------
f187448d 889// Event handling
ef57d866 890// --------------------------------------------------------------------------
a324a7bc 891
bffc1eaa
GRG
892// A note on how events are processed, which is probably the most
893// difficult thing to get working right while keeping the same API
894// and functionality for all platforms.
895//
896// When GSocket detects an event, it calls wx_socket_callback, which in
897// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
898// object. OnRequest does some housekeeping, and if the event is to be
899// propagated to the user, it creates a new wxSocketEvent object and
900// posts it. The event is not processed immediately, but delayed with
901// AddPendingEvent instead. This is necessary in order to decouple the
902// event processing from wx_socket_callback; otherwise, subsequent IO
903// calls made from the user event handler would fail, as gtk callbacks
904// are not reentrant.
905//
906// Note that, unlike events, user callbacks (now deprecated) are _not_
907// decoupled from wx_socket_callback and thus they suffer from a variety
908// of problems. Avoid them where possible and use events instead.
96db102a 909
90350682
VZ
910extern "C"
911void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
912 GSocketEvent notification,
913 char *cdata)
a324a7bc
GL
914{
915 wxSocketBase *sckobj = (wxSocketBase *)cdata;
916
bffc1eaa 917 sckobj->OnRequest((wxSocketNotify) notification);
56d8adc0 918}
a324a7bc 919
bffc1eaa 920void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 921{
bffc1eaa
GRG
922 // NOTE: We duplicate some of the code in _Wait, but this doesn't
923 // hurt. It has to be here because the (GSocket) event might arrive
924 // a bit delayed, and it has to be in _Wait as well because we don't
925 // know whether the Wait functions are being used.
ef57d866 926
bffc1eaa 927 switch(notification)
d80d1aba 928 {
04e1eb03
GRG
929 case wxSOCKET_CONNECTION:
930 m_establishing = FALSE;
931 m_connected = TRUE;
932 break;
933
d3ea6527
GRG
934 // If we are in the middle of a R/W operation, do not
935 // propagate events to users. Also, filter 'late' events
936 // which are no longer valid.
ef57d866 937
04e1eb03
GRG
938 case wxSOCKET_INPUT:
939 if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
940 return;
941 break;
942
943 case wxSOCKET_OUTPUT:
944 if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
945 return;
946 break;
947
948 case wxSOCKET_LOST:
949 m_connected = FALSE;
950 m_establishing = FALSE;
951 break;
952
953 default:
954 break;
96db102a
GRG
955 }
956
f187448d
GRG
957 // Schedule the event
958
52fbdb58 959 wxSocketEventFlags flag = 0;
bffc1eaa 960 switch (notification)
f187448d
GRG
961 {
962 case GSOCK_INPUT: flag = GSOCK_INPUT_FLAG; break;
963 case GSOCK_OUTPUT: flag = GSOCK_OUTPUT_FLAG; break;
964 case GSOCK_CONNECTION: flag = GSOCK_CONNECTION_FLAG; break;
965 case GSOCK_LOST: flag = GSOCK_LOST_FLAG; break;
52fbdb58 966 default:
5c9eff30 967 wxLogWarning(_("wxSocket: unknown event!."));
52fbdb58 968 return;
f187448d
GRG
969 }
970
bffc1eaa 971 if (((m_eventmask & flag) == flag) && m_notify)
d80d1aba 972 {
f187448d 973 if (m_handler)
bffc1eaa
GRG
974 {
975 wxSocketEvent event(m_id);
976 event.m_event = notification;
977 event.m_clientData = m_clientData;
978 event.SetEventObject(this);
979
f187448d 980 m_handler->AddPendingEvent(event);
bffc1eaa 981 }
56d8adc0 982
bffc1eaa 983#if WXWIN_COMPATIBILITY
56d8adc0 984 if (m_cbk)
bffc1eaa
GRG
985 m_cbk(*this, notification, m_cdata);
986#endif // WXWIN_COMPATIBILITY
f4ada568 987 }
f4ada568
GL
988}
989
f187448d
GRG
990void wxSocketBase::Notify(bool notify)
991{
bffc1eaa 992 m_notify = notify;
f187448d
GRG
993}
994
995void wxSocketBase::SetNotify(wxSocketEventFlags flags)
996{
bffc1eaa 997 m_eventmask = flags;
f187448d
GRG
998}
999
71622a7a 1000void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1001{
71622a7a
GRG
1002 m_handler = &handler;
1003 m_id = id;
f4ada568
GL
1004}
1005
ef57d866
GRG
1006// --------------------------------------------------------------------------
1007// Pushback buffer
1008// --------------------------------------------------------------------------
db131261 1009
f187448d 1010void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1011{
dc5c1114
GRG
1012 if (!size) return;
1013
a324a7bc 1014 if (m_unread == NULL)
f187448d 1015 m_unread = malloc(size);
dc5c1114
GRG
1016 else
1017 {
f187448d 1018 void *tmp;
f4ada568 1019
f187448d
GRG
1020 tmp = malloc(m_unrd_size + size);
1021 memcpy((char *)tmp + size, m_unread, m_unrd_size);
41895a05 1022 free(m_unread);
a324a7bc
GL
1023
1024 m_unread = tmp;
41895a05 1025 }
31528cd3 1026
f4ada568 1027 m_unrd_size += size;
a324a7bc
GL
1028
1029 memcpy(m_unread, buffer, size);
f4ada568
GL
1030}
1031
f187448d 1032wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568
GL
1033{
1034 if (!m_unrd_size)
1035 return 0;
1036
a324a7bc
GL
1037 if (size > (m_unrd_size-m_unrd_cur))
1038 size = m_unrd_size-m_unrd_cur;
96db102a 1039
f187448d 1040 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1041
dc5c1114
GRG
1042 if (!peek)
1043 {
a324a7bc 1044 m_unrd_cur += size;
dc5c1114
GRG
1045 if (m_unrd_size == m_unrd_cur)
1046 {
f4ada568
GL
1047 free(m_unread);
1048 m_unread = NULL;
a324a7bc
GL
1049 m_unrd_size = 0;
1050 m_unrd_cur = 0;
f4ada568
GL
1051 }
1052 }
1053
1054 return size;
1055}
1056
f187448d 1057
ef57d866 1058// ==========================================================================
c3e646b4 1059// wxSocketServer
ef57d866 1060// ==========================================================================
f4ada568 1061
ef57d866
GRG
1062// --------------------------------------------------------------------------
1063// Ctor
1064// --------------------------------------------------------------------------
56d8adc0 1065
f4ada568 1066wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
71622a7a
GRG
1067 wxSocketFlags flags)
1068 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1069{
56d8adc0 1070 // Create the socket
a324a7bc 1071 m_socket = GSocket_new();
f4ada568 1072
a324a7bc 1073 if (!m_socket)
f4ada568 1074 return;
384b4373 1075
56d8adc0 1076 // Setup the socket as server
a324a7bc 1077 GSocket_SetLocal(m_socket, addr_man.GetAddress());
56d8adc0
GRG
1078 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
1079 {
a324a7bc
GL
1080 GSocket_destroy(m_socket);
1081 m_socket = NULL;
f4ada568
GL
1082 return;
1083 }
a737331d 1084
e8f4c584 1085 GSocket_SetTimeout(m_socket, m_timeout * 1000);
56d8adc0
GRG
1086 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1087 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1088 wx_socket_callback, (char *)this);
1089
f4ada568
GL
1090}
1091
ef57d866
GRG
1092// --------------------------------------------------------------------------
1093// Accept
1094// --------------------------------------------------------------------------
8c14576d 1095
d80d1aba 1096bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1097{
a324a7bc 1098 GSocket *child_socket;
f4ada568 1099
17aa2bec
GRG
1100 if (!m_socket)
1101 return FALSE;
1102
04e1eb03 1103 // If wait == FALSE, then the call should be nonblocking.
56d8adc0
GRG
1104 // When we are finished, we put the socket to blocking mode
1105 // again.
d80d1aba
GRG
1106
1107 if (!wait)
5c9eff30 1108 GSocket_SetNonBlocking(m_socket, 1);
d80d1aba 1109
a324a7bc 1110 child_socket = GSocket_WaitConnection(m_socket);
384b4373 1111
d80d1aba 1112 if (!wait)
5c9eff30 1113 GSocket_SetNonBlocking(m_socket, 0);
d80d1aba 1114
04e1eb03 1115 if (!child_socket)
d80d1aba
GRG
1116 return FALSE;
1117
71622a7a 1118 sock.m_type = wxSOCKET_BASE;
a324a7bc 1119 sock.m_socket = child_socket;
f4ada568
GL
1120 sock.m_connected = TRUE;
1121
e8f4c584 1122 GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
56d8adc0
GRG
1123 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1124 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1125 wx_socket_callback, (char *)&sock);
1126
f4ada568
GL
1127 return TRUE;
1128}
1129
d80d1aba 1130wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568
GL
1131{
1132 wxSocketBase* sock = new wxSocketBase();
1133
71622a7a 1134 sock->SetFlags(m_flags);
f4ada568 1135
d80d1aba 1136 if (!AcceptWith(*sock, wait))
c3e646b4
VZ
1137 {
1138 sock->Destroy();
1139 sock = NULL;
1140 }
f4ada568 1141
f4ada568
GL
1142 return sock;
1143}
1144
17aa2bec 1145bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1146{
af2fd961 1147 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
d80d1aba
GRG
1148}
1149
ef57d866 1150// ==========================================================================
8c14576d 1151// wxSocketClient
ef57d866 1152// ==========================================================================
f4ada568 1153
ef57d866
GRG
1154// --------------------------------------------------------------------------
1155// Ctor and dtor
1156// --------------------------------------------------------------------------
56d8adc0 1157
71622a7a
GRG
1158wxSocketClient::wxSocketClient(wxSocketFlags flags)
1159 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568
GL
1160{
1161}
1162
f4ada568
GL
1163wxSocketClient::~wxSocketClient()
1164{
1165}
1166
ef57d866
GRG
1167// --------------------------------------------------------------------------
1168// Connect
1169// --------------------------------------------------------------------------
dc5c1114 1170
791b24c4 1171bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
f4ada568 1172{
791b24c4
GRG
1173 GSocketError err;
1174
ef57d866 1175 if (m_socket)
04e1eb03
GRG
1176 {
1177 // Shutdown and destroy the socket
f4ada568 1178 Close();
a324a7bc 1179 GSocket_destroy(m_socket);
04e1eb03 1180 }
a324a7bc 1181
a324a7bc 1182 m_socket = GSocket_new();
d80d1aba
GRG
1183 m_connected = FALSE;
1184 m_establishing = FALSE;
384b4373 1185
a324a7bc 1186 if (!m_socket)
f4ada568 1187 return FALSE;
384b4373 1188
e8f4c584 1189 GSocket_SetTimeout(m_socket, m_timeout * 1000);
96db102a
GRG
1190 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1191 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1192 wx_socket_callback, (char *)this);
56d8adc0 1193
04e1eb03 1194 // If wait == FALSE, then the call should be nonblocking.
56d8adc0
GRG
1195 // When we are finished, we put the socket to blocking mode
1196 // again.
f4ada568 1197
791b24c4 1198 if (!wait)
5c9eff30 1199 GSocket_SetNonBlocking(m_socket, 1);
791b24c4 1200
a324a7bc 1201 GSocket_SetPeer(m_socket, addr_man.GetAddress());
791b24c4
GRG
1202 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
1203
1204 if (!wait)
5c9eff30 1205 GSocket_SetNonBlocking(m_socket, 0);
791b24c4
GRG
1206
1207 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1208 {
1209 if (err == GSOCK_WOULDBLOCK)
1210 m_establishing = TRUE;
1211
f4ada568 1212 return FALSE;
56d8adc0 1213 }
9111db68 1214
f4ada568
GL
1215 m_connected = TRUE;
1216 return TRUE;
1217}
1218
d80d1aba 1219bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1220{
af2fd961 1221 if (m_connected) // Already connected
d80d1aba
GRG
1222 return TRUE;
1223
af2fd961 1224 if (!m_establishing || !m_socket) // No connection in progress
d80d1aba
GRG
1225 return FALSE;
1226
2b396caa
GRG
1227 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1228 GSOCK_LOST_FLAG);
f4ada568
GL
1229}
1230
ef57d866 1231// ==========================================================================
dc5c1114 1232// wxDatagramSocket
ef57d866 1233// ==========================================================================
dc5c1114
GRG
1234
1235/* NOTE: experimental stuff - might change */
1236
71622a7a
GRG
1237wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr,
1238 wxSocketFlags flags )
1239 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114
GRG
1240{
1241 // Create the socket
1242 m_socket = GSocket_new();
1243
1244 if(!m_socket)
1245 return;
1246
1247 // Setup the socket as non connection oriented
1248 GSocket_SetLocal(m_socket, addr.GetAddress());
1249 if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
1250 {
1251 GSocket_destroy(m_socket);
1252 m_socket = NULL;
1253 return;
1254 }
1255
1256 // Initialize all stuff
1257 m_connected = FALSE;
1258 m_establishing = FALSE;
1259 GSocket_SetTimeout( m_socket, m_timeout );
1260 GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1261 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1262 wx_socket_callback, (char*)this );
1263
1264}
1265
1266wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 1267 void* buf,
dc5c1114
GRG
1268 wxUint32 nBytes )
1269{
1270 Read(buf, nBytes);
1271 GetPeer(addr);
1272 return (*this);
1273}
1274
1275wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
f187448d 1276 const void* buf,
dc5c1114
GRG
1277 wxUint32 nBytes )
1278{
1279 GSocket_SetPeer(m_socket, addr.GetAddress());
1280 Write(buf, nBytes);
1281 return (*this);
1282}
1283
ef57d866 1284// ==========================================================================
a58d5df4 1285// wxSocketModule
ef57d866 1286// ==========================================================================
dc5c1114 1287
bffc1eaa 1288class WXDLLEXPORT wxSocketModule : public wxModule
dc5c1114 1289{
dc5c1114 1290public:
6c0d0845
VZ
1291 virtual bool OnInit()
1292 {
1293 // wxSocketBase will call GSocket_Init() itself when/if needed
1294 return TRUE;
1295 }
1296
1297 virtual void OnExit()
1298 {
1299 if ( wxSocketBase::IsInitialized() )
1300 wxSocketBase::Shutdown();
1301 }
1302
1303private:
1304 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
1305};
1306
1307IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1308
35a4dab7
GL
1309#endif
1310 // wxUSE_SOCKETS