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