]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
[ 1473731 ] 'wxColourBase and wxString <-> wxColour implementation'
[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__
8e3f3880 20 #pragma hdrstop
fcc6dddd
JS
21#endif
22
35a4dab7
GL
23#if wxUSE_SOCKETS
24
df91131c
WS
25#include "wx/socket.h"
26
8e3f3880
WS
27#ifndef WX_PRECOMP
28 #include "wx/object.h"
df91131c 29 #include "wx/string.h"
8e3f3880
WS
30#endif
31
dc5c1114 32#include "wx/app.h"
e2478fde 33#include "wx/apptrait.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 41#include "wx/sckaddr.h"
204b046e 42#include "wx/datetime.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 100
17a1ebd1 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()") );
8d7eaf91 165 if ( --m_countInit == 0 )
6c0d0845
VZ
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
3c57bda5 700 bool has_event_loop = wxTheApp->GetTraits() ? (wxTheApp->GetTraits()->GetSocketGUIFunctionsTable() ? true : false) : false;
f01bca89 701
bffc1eaa 702 // Wait in an active polling loop.
af2fd961 703 //
bffc1eaa
GRG
704 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
705 // hurt. It has to be here because the (GSocket) event might arrive
706 // a bit delayed, and it has to be in OnRequest as well because we
707 // don't know whether the Wait functions are being used.
af2fd961 708 //
96db102a 709 // Do this at least once (important if timeout == 0, when
d3ea6527 710 // we are just polling). Also, if just polling, do not yield.
ef57d866 711
204b046e
KH
712 wxDateTime current_time = wxDateTime::UNow();
713 unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout;
d775fa82 714 bool done = false;
204b046e
KH
715 bool valid_result = false;
716
8e3f3880 717 if (!has_event_loop)
f01bca89 718 {
204b046e
KH
719 // This is used to avoid a busy loop on wxBase - having a select
720 // timeout of 50 ms per iteration should be enough.
721 if (timeout > 50)
722 m_socket->SetTimeout(50);
723 else
724 m_socket->SetTimeout(timeout);
f01bca89 725 }
71622a7a
GRG
726
727 while (!done)
56d8adc0 728 {
8b6fc577 729 result = m_socket->Select(flags | GSOCK_LOST_FLAG);
af2fd961 730
af2fd961
GRG
731 // Incoming connection (server) or connection established (client)
732 if (result & GSOCK_CONNECTION_FLAG)
733 {
d775fa82
WS
734 m_connected = true;
735 m_establishing = false;
204b046e
KH
736 valid_result = true;
737 break;
af2fd961
GRG
738 }
739
04e1eb03 740 // Data available or output buffer ready
81b92e17 741 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
af2fd961 742 {
204b046e
KH
743 valid_result = true;
744 break;
af2fd961
GRG
745 }
746
c0043a50
GRG
747 // Connection lost
748 if (result & GSOCK_LOST_FLAG)
749 {
d775fa82
WS
750 m_connected = false;
751 m_establishing = false;
204b046e
KH
752 valid_result = ((flags & GSOCK_LOST_FLAG) != 0);
753 break;
c0043a50
GRG
754 }
755
81b92e17 756 // Wait more?
204b046e
KH
757 current_time = wxDateTime::UNow();
758 int time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond());
759 if ((!timeout) || (time_left <= 0) || (m_interrupt))
d775fa82 760 done = true;
d3ea6527 761 else
204b046e 762 {
8e3f3880 763 if (has_event_loop)
f01bca89
JS
764 {
765 PROCESS_EVENTS();
766 }
8e3f3880 767 else
f01bca89 768 {
204b046e
KH
769 // If there's less than 50 ms left, just call select with that timeout.
770 if (time_left < 50)
771 m_socket->SetTimeout(time_left);
f01bca89
JS
772 }
773 }
56d8adc0 774 }
f4ada568 775
204b046e 776 // Set timeout back to original value (we overwrote it for polling)
f01bca89
JS
777 if (!has_event_loop)
778 m_socket->SetTimeout(m_timeout*1000);
204b046e
KH
779
780 return valid_result;
f4ada568 781}
f4ada568 782
a737331d 783bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 784{
7fb0a11d
WS
785 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
786 GSOCK_OUTPUT_FLAG |
787 GSOCK_CONNECTION_FLAG |
788 GSOCK_LOST_FLAG);
f4ada568 789}
f4ada568 790
a737331d 791bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 792{
ef57d866 793 // Check pushback buffer before entering _Wait
96db102a 794 if (m_unread)
d775fa82 795 return true;
96db102a 796
ef57d866 797 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
90e572f1 798 // _Wait because of the semantics of WaitForRead: a return
d775fa82 799 // value of true means that a GSocket_Read call will return
ef57d866
GRG
800 // immediately, not that there is actually data to read.
801
802 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
803 GSOCK_LOST_FLAG);
f4ada568
GL
804}
805
bfa7bf7d 806
a737331d 807bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 808{
7fb0a11d 809 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
a737331d 810}
f4ada568 811
a737331d
GL
812bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
813{
7fb0a11d 814 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
f4ada568 815}
a737331d 816
ef57d866
GRG
817// --------------------------------------------------------------------------
818// Miscellaneous
819// --------------------------------------------------------------------------
820
821//
822// Get local or peer address
823//
824
825bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
826{
827 GAddress *peer;
828
829 if (!m_socket)
d775fa82 830 return false;
ef57d866 831
8b6fc577 832 peer = m_socket->GetPeer();
007c77ab
RL
833
834 // copying a null address would just trigger an assert anyway
835
836 if (!peer)
d775fa82 837 return false;
007c77ab 838
ef57d866
GRG
839 addr_man.SetAddress(peer);
840 GAddress_destroy(peer);
841
d775fa82 842 return true;
ef57d866
GRG
843}
844
845bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
846{
7fb0a11d 847 GAddress *local;
ef57d866 848
7fb0a11d
WS
849 if (!m_socket)
850 return false;
ef57d866 851
7fb0a11d
WS
852 local = m_socket->GetLocal();
853 addr_man.SetAddress(local);
854 GAddress_destroy(local);
ef57d866 855
7fb0a11d 856 return true;
ef57d866
GRG
857}
858
859//
860// Save and restore socket state
861//
862
863void wxSocketBase::SaveState()
864{
7fb0a11d 865 wxSocketState *state;
ef57d866 866
7fb0a11d 867 state = new wxSocketState();
ef57d866 868
7fb0a11d
WS
869 state->m_flags = m_flags;
870 state->m_notify = m_notify;
871 state->m_eventmask = m_eventmask;
872 state->m_clientData = m_clientData;
ef57d866 873
7fb0a11d 874 m_states.Append(state);
ef57d866
GRG
875}
876
877void wxSocketBase::RestoreState()
878{
7fb0a11d
WS
879 wxList::compatibility_iterator node;
880 wxSocketState *state;
ef57d866 881
7fb0a11d
WS
882 node = m_states.GetLast();
883 if (!node)
884 return;
ef57d866 885
7fb0a11d 886 state = (wxSocketState *)node->GetData();
ef57d866 887
7fb0a11d
WS
888 m_flags = state->m_flags;
889 m_notify = state->m_notify;
890 m_eventmask = state->m_eventmask;
891 m_clientData = state->m_clientData;
37340c48 892
7fb0a11d
WS
893 m_states.Erase(node);
894 delete state;
ef57d866
GRG
895}
896
897//
898// Timeout and flags
899//
900
17aa2bec
GRG
901void wxSocketBase::SetTimeout(long seconds)
902{
7fb0a11d 903 m_timeout = seconds;
17aa2bec 904
7fb0a11d
WS
905 if (m_socket)
906 m_socket->SetTimeout(m_timeout * 1000);
17aa2bec
GRG
907}
908
71622a7a 909void wxSocketBase::SetFlags(wxSocketFlags flags)
f4ada568 910{
7fb0a11d 911 m_flags = flags;
f4ada568 912}
f0a56ab0 913
f187448d 914
ef57d866 915// --------------------------------------------------------------------------
f187448d 916// Event handling
ef57d866 917// --------------------------------------------------------------------------
a324a7bc 918
bffc1eaa
GRG
919// A note on how events are processed, which is probably the most
920// difficult thing to get working right while keeping the same API
921// and functionality for all platforms.
922//
923// When GSocket detects an event, it calls wx_socket_callback, which in
924// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
925// object. OnRequest does some housekeeping, and if the event is to be
926// propagated to the user, it creates a new wxSocketEvent object and
927// posts it. The event is not processed immediately, but delayed with
928// AddPendingEvent instead. This is necessary in order to decouple the
929// event processing from wx_socket_callback; otherwise, subsequent IO
930// calls made from the user event handler would fail, as gtk callbacks
931// are not reentrant.
932//
933// Note that, unlike events, user callbacks (now deprecated) are _not_
934// decoupled from wx_socket_callback and thus they suffer from a variety
935// of problems. Avoid them where possible and use events instead.
96db102a 936
90350682
VZ
937extern "C"
938void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
939 GSocketEvent notification,
940 char *cdata)
a324a7bc 941{
7fb0a11d 942 wxSocketBase *sckobj = (wxSocketBase *)cdata;
a324a7bc 943
7fb0a11d 944 sckobj->OnRequest((wxSocketNotify) notification);
56d8adc0 945}
a324a7bc 946
bffc1eaa 947void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 948{
bffc1eaa
GRG
949 // NOTE: We duplicate some of the code in _Wait, but this doesn't
950 // hurt. It has to be here because the (GSocket) event might arrive
951 // a bit delayed, and it has to be in _Wait as well because we don't
952 // know whether the Wait functions are being used.
ef57d866 953
bffc1eaa 954 switch(notification)
d80d1aba 955 {
04e1eb03 956 case wxSOCKET_CONNECTION:
d775fa82
WS
957 m_establishing = false;
958 m_connected = true;
04e1eb03
GRG
959 break;
960
d3ea6527
GRG
961 // If we are in the middle of a R/W operation, do not
962 // propagate events to users. Also, filter 'late' events
963 // which are no longer valid.
ef57d866 964
04e1eb03 965 case wxSOCKET_INPUT:
8b6fc577 966 if (m_reading || !m_socket->Select(GSOCK_INPUT_FLAG))
04e1eb03
GRG
967 return;
968 break;
969
970 case wxSOCKET_OUTPUT:
8b6fc577 971 if (m_writing || !m_socket->Select(GSOCK_OUTPUT_FLAG))
04e1eb03
GRG
972 return;
973 break;
974
975 case wxSOCKET_LOST:
d775fa82
WS
976 m_connected = false;
977 m_establishing = false;
04e1eb03
GRG
978 break;
979
980 default:
981 break;
96db102a
GRG
982 }
983
f187448d
GRG
984 // Schedule the event
985
52fbdb58 986 wxSocketEventFlags flag = 0;
999836aa 987 wxUnusedVar(flag);
bffc1eaa 988 switch (notification)
f187448d
GRG
989 {
990 case GSOCK_INPUT: flag = GSOCK_INPUT_FLAG; break;
991 case GSOCK_OUTPUT: flag = GSOCK_OUTPUT_FLAG; break;
992 case GSOCK_CONNECTION: flag = GSOCK_CONNECTION_FLAG; break;
993 case GSOCK_LOST: flag = GSOCK_LOST_FLAG; break;
52fbdb58 994 default:
5c9eff30 995 wxLogWarning(_("wxSocket: unknown event!."));
52fbdb58 996 return;
f187448d
GRG
997 }
998
bffc1eaa 999 if (((m_eventmask & flag) == flag) && m_notify)
d80d1aba 1000 {
f187448d 1001 if (m_handler)
bffc1eaa
GRG
1002 {
1003 wxSocketEvent event(m_id);
1004 event.m_event = notification;
1005 event.m_clientData = m_clientData;
1006 event.SetEventObject(this);
1007
f187448d 1008 m_handler->AddPendingEvent(event);
bffc1eaa 1009 }
f4ada568 1010 }
f4ada568
GL
1011}
1012
f187448d
GRG
1013void wxSocketBase::Notify(bool notify)
1014{
7fb0a11d 1015 m_notify = notify;
f187448d
GRG
1016}
1017
1018void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1019{
7fb0a11d 1020 m_eventmask = flags;
f187448d
GRG
1021}
1022
71622a7a 1023void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1024{
7fb0a11d
WS
1025 m_handler = &handler;
1026 m_id = id;
f4ada568
GL
1027}
1028
ef57d866
GRG
1029// --------------------------------------------------------------------------
1030// Pushback buffer
1031// --------------------------------------------------------------------------
db131261 1032
f187448d 1033void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1034{
dc5c1114
GRG
1035 if (!size) return;
1036
a324a7bc 1037 if (m_unread == NULL)
f187448d 1038 m_unread = malloc(size);
dc5c1114
GRG
1039 else
1040 {
f187448d 1041 void *tmp;
f4ada568 1042
f187448d
GRG
1043 tmp = malloc(m_unrd_size + size);
1044 memcpy((char *)tmp + size, m_unread, m_unrd_size);
41895a05 1045 free(m_unread);
a324a7bc
GL
1046
1047 m_unread = tmp;
41895a05 1048 }
31528cd3 1049
f4ada568 1050 m_unrd_size += size;
a324a7bc
GL
1051
1052 memcpy(m_unread, buffer, size);
f4ada568
GL
1053}
1054
f187448d 1055wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568
GL
1056{
1057 if (!m_unrd_size)
1058 return 0;
1059
a324a7bc
GL
1060 if (size > (m_unrd_size-m_unrd_cur))
1061 size = m_unrd_size-m_unrd_cur;
96db102a 1062
f187448d 1063 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1064
dc5c1114
GRG
1065 if (!peek)
1066 {
a324a7bc 1067 m_unrd_cur += size;
dc5c1114
GRG
1068 if (m_unrd_size == m_unrd_cur)
1069 {
f4ada568
GL
1070 free(m_unread);
1071 m_unread = NULL;
a324a7bc
GL
1072 m_unrd_size = 0;
1073 m_unrd_cur = 0;
f4ada568
GL
1074 }
1075 }
1076
1077 return size;
1078}
1079
f187448d 1080
ef57d866 1081// ==========================================================================
c3e646b4 1082// wxSocketServer
ef57d866 1083// ==========================================================================
f4ada568 1084
ef57d866
GRG
1085// --------------------------------------------------------------------------
1086// Ctor
1087// --------------------------------------------------------------------------
56d8adc0 1088
fbfb8bcc 1089wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
71622a7a
GRG
1090 wxSocketFlags flags)
1091 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1092{
007c77ab 1093 wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
f4ada568 1094
007c77ab 1095 m_socket = GSocket_new();
384b4373 1096
007c77ab
RL
1097 if (!m_socket)
1098 {
1099 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_new failed") );
1100 return;
1101 }
a737331d 1102
007c77ab 1103 // Setup the socket as server
56d8adc0 1104
8b6fc577 1105 m_socket->SetLocal(addr_man.GetAddress());
d775fa82 1106
74c481d1 1107 if (GetFlags() & wxSOCKET_REUSEADDR) {
8b6fc577 1108 m_socket->SetReusable();
74c481d1
VZ
1109 }
1110
8b6fc577 1111 if (m_socket->SetServer() != GSOCK_NOERROR)
007c77ab 1112 {
8b6fc577 1113 delete m_socket;
007c77ab
RL
1114 m_socket = NULL;
1115
1116 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_SetServer failed") );
1117 return;
1118 }
1119
8b6fc577
DE
1120 m_socket->SetTimeout(m_timeout * 1000);
1121 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
007c77ab
RL
1122 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1123 wx_socket_callback, (char *)this);
f4ada568
GL
1124}
1125
ef57d866
GRG
1126// --------------------------------------------------------------------------
1127// Accept
1128// --------------------------------------------------------------------------
8c14576d 1129
d80d1aba 1130bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1131{
a324a7bc 1132 GSocket *child_socket;
f4ada568 1133
17aa2bec 1134 if (!m_socket)
d775fa82 1135 return false;
17aa2bec 1136
d775fa82 1137 // If wait == false, then the call should be nonblocking.
56d8adc0
GRG
1138 // When we are finished, we put the socket to blocking mode
1139 // again.
d80d1aba
GRG
1140
1141 if (!wait)
8b6fc577 1142 m_socket->SetNonBlocking(1);
d80d1aba 1143
8b6fc577 1144 child_socket = m_socket->WaitConnection();
384b4373 1145
d80d1aba 1146 if (!wait)
8b6fc577 1147 m_socket->SetNonBlocking(0);
d80d1aba 1148
04e1eb03 1149 if (!child_socket)
d775fa82 1150 return false;
d80d1aba 1151
71622a7a 1152 sock.m_type = wxSOCKET_BASE;
a324a7bc 1153 sock.m_socket = child_socket;
d775fa82 1154 sock.m_connected = true;
f4ada568 1155
8b6fc577
DE
1156 sock.m_socket->SetTimeout(sock.m_timeout * 1000);
1157 sock.m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
56d8adc0
GRG
1158 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1159 wx_socket_callback, (char *)&sock);
1160
d775fa82 1161 return true;
f4ada568
GL
1162}
1163
d80d1aba 1164wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568
GL
1165{
1166 wxSocketBase* sock = new wxSocketBase();
1167
71622a7a 1168 sock->SetFlags(m_flags);
f4ada568 1169
d80d1aba 1170 if (!AcceptWith(*sock, wait))
c3e646b4
VZ
1171 {
1172 sock->Destroy();
1173 sock = NULL;
1174 }
f4ada568 1175
f4ada568
GL
1176 return sock;
1177}
1178
17aa2bec 1179bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1180{
7fb0a11d 1181 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
d80d1aba
GRG
1182}
1183
bfa7bf7d
VZ
1184bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1185{
11734f8a
JS
1186 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1187
8b6fc577 1188 if (m_socket->GetSockOpt(level, optname, optval, optlen)
bfa7bf7d
VZ
1189 != GSOCK_NOERROR)
1190 {
d775fa82 1191 return false;
bfa7bf7d 1192 }
d775fa82 1193 return true;
bfa7bf7d
VZ
1194}
1195
37340c48 1196bool wxSocketBase::SetOption(int level, int optname, const void *optval,
bfa7bf7d
VZ
1197 int optlen)
1198{
11734f8a 1199 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
8e3f3880 1200
8b6fc577 1201 if (m_socket->SetSockOpt(level, optname, optval, optlen)
bfa7bf7d
VZ
1202 != GSOCK_NOERROR)
1203 {
d775fa82 1204 return false;
bfa7bf7d 1205 }
d775fa82 1206 return true;
bfa7bf7d
VZ
1207}
1208
30bbf68d 1209bool wxSocketBase::SetLocal(wxIPV4address& local)
33d925b0
KH
1210{
1211 GAddress* la = local.GetAddress();
1212
30bbf68d 1213 // If the address is valid, save it for use when we call Connect
33d925b0
KH
1214 if (la && la->m_addr)
1215 {
30bbf68d 1216 m_localAddress = local;
33d925b0
KH
1217
1218 return true;
1219 }
1220
1221 return false;
1222}
1223
ef57d866 1224// ==========================================================================
8c14576d 1225// wxSocketClient
ef57d866 1226// ==========================================================================
f4ada568 1227
ef57d866
GRG
1228// --------------------------------------------------------------------------
1229// Ctor and dtor
1230// --------------------------------------------------------------------------
56d8adc0 1231
71622a7a
GRG
1232wxSocketClient::wxSocketClient(wxSocketFlags flags)
1233 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568
GL
1234{
1235}
1236
f4ada568
GL
1237wxSocketClient::~wxSocketClient()
1238{
1239}
1240
ef57d866
GRG
1241// --------------------------------------------------------------------------
1242// Connect
1243// --------------------------------------------------------------------------
dc5c1114 1244
33d925b0 1245bool wxSocketClient::DoConnect(wxSockAddress& addr_man, wxSockAddress* local, bool wait)
f4ada568 1246{
791b24c4
GRG
1247 GSocketError err;
1248
ef57d866 1249 if (m_socket)
04e1eb03
GRG
1250 {
1251 // Shutdown and destroy the socket
f4ada568 1252 Close();
8b6fc577 1253 delete m_socket;
04e1eb03 1254 }
a324a7bc 1255
a324a7bc 1256 m_socket = GSocket_new();
d775fa82
WS
1257 m_connected = false;
1258 m_establishing = false;
384b4373 1259
a324a7bc 1260 if (!m_socket)
d775fa82 1261 return false;
384b4373 1262
8b6fc577
DE
1263 m_socket->SetTimeout(m_timeout * 1000);
1264 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
96db102a
GRG
1265 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1266 wx_socket_callback, (char *)this);
56d8adc0 1267
d775fa82 1268 // If wait == false, then the call should be nonblocking.
56d8adc0
GRG
1269 // When we are finished, we put the socket to blocking mode
1270 // again.
f4ada568 1271
791b24c4 1272 if (!wait)
8b6fc577 1273 m_socket->SetNonBlocking(1);
791b24c4 1274
33d925b0
KH
1275 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1276 if (GetFlags() & wxSOCKET_REUSEADDR)
1277 {
1278 m_socket->SetReusable();
1279 }
1280
30bbf68d
KH
1281 // If no local address was passed and one has been set, use the one that was Set
1282 if (!local && m_localAddress.GetAddress())
1283 {
1284 local = &m_localAddress;
1285 }
1286
33d925b0
KH
1287 // Bind to the local IP address and port, when provided
1288 if (local)
1289 {
1290 GAddress* la = local->GetAddress();
1291
1292 if (la && la->m_addr)
1293 m_socket->SetLocal(la);
1294 }
1295
8b6fc577
DE
1296 m_socket->SetPeer(addr_man.GetAddress());
1297 err = m_socket->Connect(GSOCK_STREAMED);
791b24c4
GRG
1298
1299 if (!wait)
8b6fc577 1300 m_socket->SetNonBlocking(0);
791b24c4
GRG
1301
1302 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1303 {
1304 if (err == GSOCK_WOULDBLOCK)
d775fa82 1305 m_establishing = true;
56d8adc0 1306
d775fa82 1307 return false;
56d8adc0 1308 }
9111db68 1309
d775fa82
WS
1310 m_connected = true;
1311 return true;
f4ada568
GL
1312}
1313
33d925b0
KH
1314bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1315{
7fb0a11d 1316 return (DoConnect(addr_man, NULL, wait));
33d925b0
KH
1317}
1318
1319bool wxSocketClient::Connect(wxSockAddress& addr_man, wxSockAddress& local, bool wait)
1320{
7fb0a11d 1321 return (DoConnect(addr_man, &local, wait));
33d925b0
KH
1322}
1323
d80d1aba 1324bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1325{
7fb0a11d
WS
1326 if (m_connected) // Already connected
1327 return true;
d80d1aba 1328
7fb0a11d
WS
1329 if (!m_establishing || !m_socket) // No connection in progress
1330 return false;
d80d1aba 1331
7fb0a11d
WS
1332 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1333 GSOCK_LOST_FLAG);
f4ada568
GL
1334}
1335
ef57d866 1336// ==========================================================================
dc5c1114 1337// wxDatagramSocket
ef57d866 1338// ==========================================================================
dc5c1114
GRG
1339
1340/* NOTE: experimental stuff - might change */
1341
fbfb8bcc 1342wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
1343 wxSocketFlags flags )
1344 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114 1345{
7fb0a11d
WS
1346 // Create the socket
1347 m_socket = GSocket_new();
dc5c1114 1348
7fb0a11d
WS
1349 if(!m_socket)
1350 {
1351 wxFAIL_MSG( _T("datagram socket not new'd") );
1352 return;
1353 }
1354 // Setup the socket as non connection oriented
1355 m_socket->SetLocal(addr.GetAddress());
1356 if( m_socket->SetNonOriented() != GSOCK_NOERROR )
1357 {
1358 delete m_socket;
1359 m_socket = NULL;
1360 return;
1361 }
dc5c1114 1362
7fb0a11d
WS
1363 // Initialize all stuff
1364 m_connected = false;
1365 m_establishing = false;
1366 m_socket->SetTimeout( m_timeout );
1367 m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1368 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1369 wx_socket_callback, (char*)this );
dc5c1114
GRG
1370}
1371
1372wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 1373 void* buf,
dc5c1114
GRG
1374 wxUint32 nBytes )
1375{
1376 Read(buf, nBytes);
1377 GetPeer(addr);
1378 return (*this);
1379}
1380
fbfb8bcc 1381wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 1382 const void* buf,
dc5c1114
GRG
1383 wxUint32 nBytes )
1384{
11734f8a 1385 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
8e3f3880 1386
8b6fc577 1387 m_socket->SetPeer(addr.GetAddress());
dc5c1114
GRG
1388 Write(buf, nBytes);
1389 return (*this);
1390}
1391
ef57d866 1392// ==========================================================================
a58d5df4 1393// wxSocketModule
ef57d866 1394// ==========================================================================
dc5c1114 1395
ed4c6c69 1396class wxSocketModule : public wxModule
dc5c1114 1397{
dc5c1114 1398public:
6c0d0845
VZ
1399 virtual bool OnInit()
1400 {
1401 // wxSocketBase will call GSocket_Init() itself when/if needed
d775fa82 1402 return true;
6c0d0845
VZ
1403 }
1404
1405 virtual void OnExit()
1406 {
1407 if ( wxSocketBase::IsInitialized() )
1408 wxSocketBase::Shutdown();
1409 }
1410
1411private:
1412 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
1413};
1414
1415IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1416
35a4dab7
GL
1417#endif
1418 // wxUSE_SOCKETS