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