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