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