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