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