]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
Added wxDataViewSortedListModel, which doesn't work
[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
30bbf68d 1206bool wxSocketBase::SetLocal(wxIPV4address& local)
33d925b0
KH
1207{
1208 GAddress* la = local.GetAddress();
1209
30bbf68d 1210 // If the address is valid, save it for use when we call Connect
33d925b0
KH
1211 if (la && la->m_addr)
1212 {
30bbf68d 1213 m_localAddress = local;
33d925b0
KH
1214
1215 return true;
1216 }
1217
1218 return false;
1219}
1220
ef57d866 1221// ==========================================================================
8c14576d 1222// wxSocketClient
ef57d866 1223// ==========================================================================
f4ada568 1224
ef57d866
GRG
1225// --------------------------------------------------------------------------
1226// Ctor and dtor
1227// --------------------------------------------------------------------------
56d8adc0 1228
71622a7a
GRG
1229wxSocketClient::wxSocketClient(wxSocketFlags flags)
1230 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568
GL
1231{
1232}
1233
f4ada568
GL
1234wxSocketClient::~wxSocketClient()
1235{
1236}
1237
ef57d866
GRG
1238// --------------------------------------------------------------------------
1239// Connect
1240// --------------------------------------------------------------------------
dc5c1114 1241
33d925b0 1242bool wxSocketClient::DoConnect(wxSockAddress& addr_man, wxSockAddress* local, bool wait)
f4ada568 1243{
791b24c4
GRG
1244 GSocketError err;
1245
ef57d866 1246 if (m_socket)
04e1eb03
GRG
1247 {
1248 // Shutdown and destroy the socket
f4ada568 1249 Close();
8b6fc577 1250 delete m_socket;
04e1eb03 1251 }
a324a7bc 1252
a324a7bc 1253 m_socket = GSocket_new();
d775fa82
WS
1254 m_connected = false;
1255 m_establishing = false;
384b4373 1256
a324a7bc 1257 if (!m_socket)
d775fa82 1258 return false;
384b4373 1259
8b6fc577
DE
1260 m_socket->SetTimeout(m_timeout * 1000);
1261 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
96db102a
GRG
1262 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1263 wx_socket_callback, (char *)this);
56d8adc0 1264
d775fa82 1265 // If wait == false, then the call should be nonblocking.
56d8adc0
GRG
1266 // When we are finished, we put the socket to blocking mode
1267 // again.
f4ada568 1268
791b24c4 1269 if (!wait)
8b6fc577 1270 m_socket->SetNonBlocking(1);
791b24c4 1271
33d925b0
KH
1272 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1273 if (GetFlags() & wxSOCKET_REUSEADDR)
1274 {
1275 m_socket->SetReusable();
1276 }
1277
30bbf68d
KH
1278 // If no local address was passed and one has been set, use the one that was Set
1279 if (!local && m_localAddress.GetAddress())
1280 {
1281 local = &m_localAddress;
1282 }
1283
33d925b0
KH
1284 // Bind to the local IP address and port, when provided
1285 if (local)
1286 {
1287 GAddress* la = local->GetAddress();
1288
1289 if (la && la->m_addr)
1290 m_socket->SetLocal(la);
1291 }
1292
8b6fc577
DE
1293 m_socket->SetPeer(addr_man.GetAddress());
1294 err = m_socket->Connect(GSOCK_STREAMED);
791b24c4
GRG
1295
1296 if (!wait)
8b6fc577 1297 m_socket->SetNonBlocking(0);
791b24c4
GRG
1298
1299 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1300 {
1301 if (err == GSOCK_WOULDBLOCK)
d775fa82 1302 m_establishing = true;
56d8adc0 1303
d775fa82 1304 return false;
56d8adc0 1305 }
9111db68 1306
d775fa82
WS
1307 m_connected = true;
1308 return true;
f4ada568
GL
1309}
1310
33d925b0
KH
1311bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1312{
1313 return (DoConnect(addr_man, NULL, wait));
1314}
1315
1316bool wxSocketClient::Connect(wxSockAddress& addr_man, wxSockAddress& local, bool wait)
1317{
1318 return (DoConnect(addr_man, &local, wait));
1319}
1320
d80d1aba 1321bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1322{
af2fd961 1323 if (m_connected) // Already connected
d775fa82 1324 return true;
d80d1aba 1325
af2fd961 1326 if (!m_establishing || !m_socket) // No connection in progress
d775fa82 1327 return false;
d80d1aba 1328
2b396caa
GRG
1329 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1330 GSOCK_LOST_FLAG);
f4ada568
GL
1331}
1332
ef57d866 1333// ==========================================================================
dc5c1114 1334// wxDatagramSocket
ef57d866 1335// ==========================================================================
dc5c1114
GRG
1336
1337/* NOTE: experimental stuff - might change */
1338
fbfb8bcc 1339wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
1340 wxSocketFlags flags )
1341 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114
GRG
1342{
1343 // Create the socket
1344 m_socket = GSocket_new();
1345
1346 if(!m_socket)
bfa7bf7d
VZ
1347 {
1348 wxASSERT_MSG( 0, _T("datagram socket not new'd") );
dc5c1114 1349 return;
bfa7bf7d 1350 }
dc5c1114 1351 // Setup the socket as non connection oriented
8b6fc577
DE
1352 m_socket->SetLocal(addr.GetAddress());
1353 if( m_socket->SetNonOriented() != GSOCK_NOERROR )
dc5c1114 1354 {
8b6fc577 1355 delete m_socket;
dc5c1114
GRG
1356 m_socket = NULL;
1357 return;
1358 }
1359
1360 // Initialize all stuff
d775fa82
WS
1361 m_connected = false;
1362 m_establishing = false;
8b6fc577
DE
1363 m_socket->SetTimeout( m_timeout );
1364 m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
dc5c1114
GRG
1365 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1366 wx_socket_callback, (char*)this );
1367
1368}
1369
1370wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 1371 void* buf,
dc5c1114
GRG
1372 wxUint32 nBytes )
1373{
1374 Read(buf, nBytes);
1375 GetPeer(addr);
1376 return (*this);
1377}
1378
fbfb8bcc 1379wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 1380 const void* buf,
dc5c1114
GRG
1381 wxUint32 nBytes )
1382{
11734f8a
JS
1383 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1384
8b6fc577 1385 m_socket->SetPeer(addr.GetAddress());
dc5c1114
GRG
1386 Write(buf, nBytes);
1387 return (*this);
1388}
1389
ef57d866 1390// ==========================================================================
a58d5df4 1391// wxSocketModule
ef57d866 1392// ==========================================================================
dc5c1114 1393
ed4c6c69 1394class wxSocketModule : public wxModule
dc5c1114 1395{
dc5c1114 1396public:
6c0d0845
VZ
1397 virtual bool OnInit()
1398 {
1399 // wxSocketBase will call GSocket_Init() itself when/if needed
d775fa82 1400 return true;
6c0d0845
VZ
1401 }
1402
1403 virtual void OnExit()
1404 {
1405 if ( wxSocketBase::IsInitialized() )
1406 wxSocketBase::Shutdown();
1407 }
1408
1409private:
1410 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
1411};
1412
1413IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1414
35a4dab7
GL
1415#endif
1416 // wxUSE_SOCKETS
007c77ab
RL
1417
1418// vi:sts=4:sw=4:et