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