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