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