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