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