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