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