]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
add PostSizeEvent() and use it in wxMSW status bar code (#9795)
[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 =
c9157492
VZ
206 m_error =
207 m_closed = false;
71622a7a
GRG
208 m_lcount = 0;
209 m_timeout = 600;
d775fa82 210 m_beingDeleted = false;
71622a7a
GRG
211
212 // pushback buffer
213 m_unread = NULL;
214 m_unrd_size = 0;
215 m_unrd_cur = 0;
216
217 // events
d775fa82 218 m_id = wxID_ANY;
f187448d
GRG
219 m_handler = NULL;
220 m_clientData = NULL;
d775fa82 221 m_notify = false;
bffc1eaa 222 m_eventmask = 0;
6c0d0845
VZ
223
224 if ( !IsInitialized() )
225 {
226 // this Initialize() will be undone by wxSocketModule::OnExit(), all the
227 // other calls to it should be matched by a call to Shutdown()
228 Initialize();
229 }
f4ada568
GL
230}
231
f187448d
GRG
232wxSocketBase::wxSocketBase()
233{
234 Init();
235}
71622a7a
GRG
236
237wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
f4ada568 238{
71622a7a
GRG
239 Init();
240
241 m_flags = flags;
242 m_type = type;
f4ada568
GL
243}
244
f4ada568
GL
245wxSocketBase::~wxSocketBase()
246{
9181a383
GRG
247 // Just in case the app called Destroy() *and* then deleted
248 // the socket immediately: don't leave dangling pointers.
e2478fde
VZ
249 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
250 if ( traits )
251 traits->RemoveFromPendingDelete(this);
a737331d 252
56d8adc0 253 // Shutdown and close the socket
9181a383
GRG
254 if (!m_beingDeleted)
255 Close();
f4ada568 256
56d8adc0 257 // Destroy the GSocket object
a324a7bc 258 if (m_socket)
8b6fc577 259 delete m_socket;
9181a383
GRG
260
261 // Free the pushback buffer
262 if (m_unread)
263 free(m_unread);
f4ada568
GL
264}
265
ef57d866
GRG
266bool wxSocketBase::Destroy()
267{
268 // Delayed destruction: the socket will be deleted during the next
269 // idle loop iteration. This ensures that all pending events have
270 // been processed.
d775fa82 271 m_beingDeleted = true;
9181a383
GRG
272
273 // Shutdown and close the socket
ef57d866
GRG
274 Close();
275
bffc1eaa 276 // Supress events from now on
d775fa82 277 Notify(false);
bffc1eaa 278
e2478fde
VZ
279 // schedule this object for deletion
280 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
281 if ( traits )
282 {
283 // let the traits object decide what to do with us
284 traits->ScheduleForDestroy(this);
285 }
286 else // no app or no traits
287 {
288 // in wxBase we might have no app object at all, don't leak memory
289 delete this;
290 }
ef57d866 291
d775fa82 292 return true;
ef57d866 293}
9181a383 294
ef57d866 295// --------------------------------------------------------------------------
bffc1eaa 296// Basic IO calls
ef57d866
GRG
297// --------------------------------------------------------------------------
298
299// The following IO operations update m_error and m_lcount:
300// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
301//
302// TODO: Should Connect, Accept and AcceptWith update m_error?
303
f4ada568
GL
304bool wxSocketBase::Close()
305{
81b92e17 306 // Interrupt pending waits
02d15cad 307 InterruptWait();
81b92e17 308
31528cd3 309 if (m_socket)
8c14576d 310 {
56d8adc0 311 // Disable callbacks
8b6fc577 312 m_socket->UnsetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
56d8adc0 313 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
f4ada568 314
56d8adc0 315 // Shutdown the connection
8b6fc577 316 m_socket->Shutdown();
f4ada568
GL
317 }
318
d775fa82
WS
319 m_connected = false;
320 m_establishing = false;
321 return true;
f4ada568
GL
322}
323
f187448d 324wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 325{
96db102a 326 // Mask read events
d775fa82 327 m_reading = true;
a324a7bc 328
96db102a 329 m_lcount = _Read(buffer, nbytes);
17aa2bec 330
d3ea6527
GRG
331 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
332 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
333 m_error = (m_lcount != nbytes);
334 else
335 m_error = (m_lcount == 0);
f4ada568 336
dc5c1114 337 // Allow read events from now on
d775fa82 338 m_reading = false;
17aa2bec 339
96db102a
GRG
340 return *this;
341}
342
c9157492 343wxUint32 wxSocketBase::_Read(void* buffer_, wxUint32 nbytes)
96db102a 344{
c9157492
VZ
345 char *buffer = (char *)buffer_;
346
96db102a 347 int total;
a324a7bc 348
04e1eb03 349 // Try the pushback buffer first
d775fa82 350 total = GetPushback(buffer, nbytes, false);
96db102a 351 nbytes -= total;
f187448d 352 buffer = (char *)buffer + total;
96db102a 353
5f3629ba
GRG
354 // Return now in one of the following cases:
355 // - the socket is invalid,
635f2bad 356 // - we got all the data
5f3629ba 357 if ( !m_socket ||
635f2bad 358 !nbytes )
96db102a 359 return total;
f4ada568 360
af2fd961 361 // Possible combinations (they are checked in this order)
81b92e17 362 // wxSOCKET_NOWAIT
5c9eff30 363 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
81b92e17
GRG
364 // wxSOCKET_BLOCK
365 // wxSOCKET_NONE
af2fd961 366 //
999836aa 367 int ret;
81b92e17 368 if (m_flags & wxSOCKET_NOWAIT)
af2fd961 369 {
8b6fc577 370 m_socket->SetNonBlocking(1);
c9157492 371 ret = m_socket->Read(buffer, nbytes);
8b6fc577 372 m_socket->SetNonBlocking(0);
af2fd961 373
c9157492
VZ
374 if ( ret < 0 )
375 return 0;
376
377 total += ret;
af2fd961 378 }
c9157492 379 else // blocking socket
56d8adc0 380 {
c9157492 381 for ( ;; )
56d8adc0 382 {
c9157492 383 // dispatch events unless disabled
5c9eff30
GRG
384 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
385 break;
81b92e17 386
c9157492
VZ
387 ret = m_socket->Read(buffer, nbytes);
388 if ( ret == 0 )
389 {
390 // for connection-oriented (e.g. TCP) sockets we can only read 0
391 // bytes if the other end has been closed, and for connectionless
392 // ones (UDP) this flag doesn't make sense anyhow so we can set it to
393 // true too without doing any harm
394 m_closed = true;
395 break;
396 }
a324a7bc 397
c9157492 398 if ( ret < 0 )
81b92e17 399 {
c9157492
VZ
400 // this will be always interpreted as error by Read()
401 return 0;
81b92e17 402 }
a324a7bc 403
c9157492
VZ
404 total += ret;
405
406 // if wxSOCKET_WAITALL is not set, we can leave now as we did read
407 // something
408 if ( !(m_flags & wxSOCKET_WAITALL) )
409 break;
410
411 // otherwise check if read the maximal requested amount of data
412 nbytes -= ret;
413 if ( !nbytes )
414 break;
415
416 // we didn't, so continue reading
417 buffer = (char *)buffer + ret;
81b92e17 418 }
a324a7bc 419 }
f4ada568 420
96db102a 421 return total;
f4ada568
GL
422}
423
f187448d 424wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
062c4861 425{
96db102a
GRG
426 wxUint32 len, len2, sig, total;
427 bool error;
17aa2bec 428 int old_flags;
17aa2bec
GRG
429 struct
430 {
96db102a
GRG
431 unsigned char sig[4];
432 unsigned char len[4];
062c4861
GL
433 } msg;
434
96db102a 435 // Mask read events
d775fa82 436 m_reading = true;
062c4861 437
96db102a 438 total = 0;
d775fa82 439 error = true;
17aa2bec 440 old_flags = m_flags;
81b92e17 441 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
17aa2bec 442
f187448d 443 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
96db102a 444 goto exit;
062c4861 445
f187448d 446 sig = (wxUint32)msg.sig[0];
96db102a
GRG
447 sig |= (wxUint32)(msg.sig[1] << 8);
448 sig |= (wxUint32)(msg.sig[2] << 16);
449 sig |= (wxUint32)(msg.sig[3] << 24);
062c4861
GL
450
451 if (sig != 0xfeeddead)
17aa2bec 452 {
5c9eff30 453 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
96db102a 454 goto exit;
17aa2bec
GRG
455 }
456
96db102a
GRG
457 len = (wxUint32)msg.len[0];
458 len |= (wxUint32)(msg.len[1] << 8);
459 len |= (wxUint32)(msg.len[2] << 16);
460 len |= (wxUint32)(msg.len[3] << 24);
461
17aa2bec
GRG
462 if (len > nbytes)
463 {
062c4861
GL
464 len2 = len - nbytes;
465 len = nbytes;
466 }
467 else
468 len2 = 0;
469
04e1eb03 470 // Don't attemp to read if the msg was zero bytes long.
96db102a 471 if (len)
17aa2bec 472 {
96db102a
GRG
473 total = _Read(buffer, len);
474
475 if (total != len)
476 goto exit;
17aa2bec
GRG
477 }
478 if (len2)
479 {
96db102a 480 char *discard_buffer = new char[MAX_DISCARD_SIZE];
17aa2bec
GRG
481 long discard_len;
482
96db102a 483 // NOTE: discarded bytes don't add to m_lcount.
17aa2bec
GRG
484 do
485 {
96db102a 486 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
479cd5de
VZ
487 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
488 len2 -= (wxUint32)discard_len;
17aa2bec
GRG
489 }
490 while ((discard_len > 0) && len2);
491
492 delete [] discard_buffer;
493
494 if (len2 != 0)
96db102a 495 goto exit;
17aa2bec 496 }
f187448d 497 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
96db102a 498 goto exit;
062c4861 499
96db102a
GRG
500 sig = (wxUint32)msg.sig[0];
501 sig |= (wxUint32)(msg.sig[1] << 8);
502 sig |= (wxUint32)(msg.sig[2] << 16);
503 sig |= (wxUint32)(msg.sig[3] << 24);
a324a7bc 504
062c4861 505 if (sig != 0xdeadfeed)
17aa2bec 506 {
5c9eff30 507 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
96db102a 508 goto exit;
17aa2bec 509 }
062c4861 510
96db102a 511 // everything was OK
d775fa82 512 error = false;
96db102a
GRG
513
514exit:
515 m_error = error;
516 m_lcount = total;
d775fa82 517 m_reading = false;
17aa2bec 518 SetFlags(old_flags);
96db102a 519
062c4861
GL
520 return *this;
521}
522
f187448d 523wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
f4ada568 524{
96db102a 525 // Mask read events
d775fa82 526 m_reading = true;
96db102a
GRG
527
528 m_lcount = _Read(buffer, nbytes);
dc5c1114 529 Pushback(buffer, m_lcount);
96db102a 530
81b92e17
GRG
531 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
532 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
533 m_error = (m_lcount != nbytes);
534 else
535 m_error = (m_lcount == 0);
536
dc5c1114 537 // Allow read events again
d775fa82 538 m_reading = false;
f4ada568
GL
539
540 return *this;
541}
542
f187448d 543wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 544{
96db102a 545 // Mask write events
d775fa82 546 m_writing = true;
56d8adc0 547
96db102a
GRG
548 m_lcount = _Write(buffer, nbytes);
549
81b92e17
GRG
550 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
551 if (m_flags & wxSOCKET_WAITALL)
96db102a
GRG
552 m_error = (m_lcount != nbytes);
553 else
554 m_error = (m_lcount == 0);
555
dc5c1114 556 // Allow write events again
d775fa82 557 m_writing = false;
96db102a 558
96db102a
GRG
559 return *this;
560}
561
c9157492 562wxUint32 wxSocketBase::_Write(const void *buffer_, wxUint32 nbytes)
96db102a 563{
c9157492
VZ
564 const char *buffer = (const char *)buffer_;
565
96db102a 566 wxUint32 total = 0;
56d8adc0 567
5c9eff30
GRG
568 // If the socket is invalid or parameters are ill, return immediately
569 if (!m_socket || !buffer || !nbytes)
96db102a 570 return 0;
a324a7bc 571
af2fd961 572 // Possible combinations (they are checked in this order)
81b92e17 573 // wxSOCKET_NOWAIT
5c9eff30 574 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
81b92e17
GRG
575 // wxSOCKET_BLOCK
576 // wxSOCKET_NONE
af2fd961 577 //
999836aa 578 int ret;
81b92e17 579 if (m_flags & wxSOCKET_NOWAIT)
af2fd961 580 {
8b6fc577 581 m_socket->SetNonBlocking(1);
c9157492 582 ret = m_socket->Write(buffer, nbytes);
8b6fc577 583 m_socket->SetNonBlocking(0);
af2fd961
GRG
584
585 if (ret > 0)
96db102a 586 total = ret;
af2fd961 587 }
c9157492 588 else // blocking socket
56d8adc0 589 {
c9157492 590 for ( ;; )
56d8adc0 591 {
5c9eff30
GRG
592 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
593 break;
81b92e17 594
c9157492
VZ
595 ret = m_socket->Write(buffer, nbytes);
596
597 // see comments for similar logic for ret handling in _Read()
598 if ( ret == 0 )
599 {
600 m_closed = true;
601 break;
602 }
5c9eff30 603
c9157492 604 if ( ret < 0 )
81b92e17 605 {
c9157492 606 return 0;
81b92e17 607 }
a324a7bc 608
c9157492
VZ
609 total += ret;
610 if ( !(m_flags & wxSOCKET_WAITALL) )
611 break;
612
613 nbytes -= ret;
614 if ( !nbytes )
615 break;
616
617 buffer = (const char *)buffer + ret;
81b92e17 618 }
56d8adc0 619 }
a324a7bc 620
96db102a 621 return total;
f4ada568
GL
622}
623
f187448d 624wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
062c4861 625{
96db102a
GRG
626 wxUint32 total;
627 bool error;
f187448d
GRG
628 struct
629 {
96db102a
GRG
630 unsigned char sig[4];
631 unsigned char len[4];
062c4861
GL
632 } msg;
633
96db102a 634 // Mask write events
d775fa82 635 m_writing = true;
96db102a 636
d775fa82 637 error = true;
96db102a 638 total = 0;
81b92e17 639 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
96db102a 640
96db102a
GRG
641 msg.sig[0] = (unsigned char) 0xad;
642 msg.sig[1] = (unsigned char) 0xde;
643 msg.sig[2] = (unsigned char) 0xed;
644 msg.sig[3] = (unsigned char) 0xfe;
062c4861 645
04e1eb03
GRG
646 msg.len[0] = (unsigned char) (nbytes & 0xff);
647 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
648 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
649 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
17aa2bec 650
f187448d 651 if (_Write(&msg, sizeof(msg)) < sizeof(msg))
96db102a
GRG
652 goto exit;
653
654 total = _Write(buffer, nbytes);
655
656 if (total < nbytes)
657 goto exit;
062c4861 658
96db102a
GRG
659 msg.sig[0] = (unsigned char) 0xed;
660 msg.sig[1] = (unsigned char) 0xfe;
661 msg.sig[2] = (unsigned char) 0xad;
662 msg.sig[3] = (unsigned char) 0xde;
062c4861 663 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
062c4861 664
f187448d 665 if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
96db102a 666 goto exit;
17aa2bec 667
96db102a 668 // everything was OK
d775fa82 669 error = false;
96db102a
GRG
670
671exit:
672 m_error = error;
673 m_lcount = total;
d775fa82 674 m_writing = false;
96db102a 675
062c4861 676 return *this;
062c4861
GL
677}
678
f187448d 679wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
f4ada568 680{
56d8adc0 681 if (nbytes != 0)
96db102a 682 Pushback(buffer, nbytes);
f4ada568 683
d775fa82 684 m_error = false;
96db102a 685 m_lcount = nbytes;
f4ada568 686
96db102a 687 return *this;
a324a7bc
GL
688}
689
96db102a 690wxSocketBase& wxSocketBase::Discard()
f4ada568 691{
04e1eb03
GRG
692 char *buffer = new char[MAX_DISCARD_SIZE];
693 wxUint32 ret;
17aa2bec 694 wxUint32 total = 0;
f4ada568 695
96db102a 696 // Mask read events
d775fa82 697 m_reading = true;
96db102a 698
81b92e17 699 SetFlags(wxSOCKET_NOWAIT);
384b4373 700
04e1eb03 701 do
8c14576d 702 {
04e1eb03
GRG
703 ret = _Read(buffer, MAX_DISCARD_SIZE);
704 total += ret;
f4ada568 705 }
04e1eb03 706 while (ret == MAX_DISCARD_SIZE);
f4ada568 707
04e1eb03 708 delete[] buffer;
17aa2bec 709 m_lcount = total;
d775fa82 710 m_error = false;
17aa2bec 711
dc5c1114 712 // Allow read events again
d775fa82 713 m_reading = false;
96db102a 714
96db102a 715 return *this;
f4ada568
GL
716}
717
ef57d866
GRG
718// --------------------------------------------------------------------------
719// Wait functions
720// --------------------------------------------------------------------------
f4ada568 721
ef57d866
GRG
722// All Wait functions poll the socket using GSocket_Select() to
723// check for the specified combination of conditions, until one
724// of these conditions become true, an error occurs, or the
725// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
726// this won't block the GUI.
f4ada568 727
bffc1eaa
GRG
728bool wxSocketBase::_Wait(long seconds,
729 long milliseconds,
d3ea6527 730 wxSocketEventFlags flags)
375abe3d 731{
56d8adc0 732 GSocketEventFlags result;
4252569b 733 long timeout; // in ms
375abe3d 734
d775fa82
WS
735 // Set this to true to interrupt ongoing waits
736 m_interrupt = false;
81b92e17 737
ef57d866 738 // Check for valid socket
af2fd961 739 if (!m_socket)
d775fa82 740 return false;
af2fd961 741
71622a7a 742 // Check for valid timeout value.
56d8adc0
GRG
743 if (seconds != -1)
744 timeout = seconds * 1000 + milliseconds;
745 else
746 timeout = m_timeout * 1000;
a324a7bc 747
2804f77d
VZ
748 // check if we are using event loop or not: normally we do in GUI but not in
749 // console applications but this can be overridden
750 const bool has_event_loop = wxEventLoop::GetActive() != NULL;
f01bca89 751
bffc1eaa 752 // Wait in an active polling loop.
af2fd961 753 //
bffc1eaa
GRG
754 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
755 // hurt. It has to be here because the (GSocket) event might arrive
756 // a bit delayed, and it has to be in OnRequest as well because we
757 // don't know whether the Wait functions are being used.
af2fd961 758 //
96db102a 759 // Do this at least once (important if timeout == 0, when
d3ea6527 760 // we are just polling). Also, if just polling, do not yield.
ef57d866 761
4252569b 762 const wxMilliClock_t time_limit = wxGetLocalTimeMillis() + timeout;
d775fa82 763 bool done = false;
204b046e
KH
764 bool valid_result = false;
765
8e3f3880 766 if (!has_event_loop)
f01bca89 767 {
204b046e
KH
768 // This is used to avoid a busy loop on wxBase - having a select
769 // timeout of 50 ms per iteration should be enough.
770 if (timeout > 50)
771 m_socket->SetTimeout(50);
772 else
773 m_socket->SetTimeout(timeout);
f01bca89 774 }
71622a7a
GRG
775
776 while (!done)
56d8adc0 777 {
8b6fc577 778 result = m_socket->Select(flags | GSOCK_LOST_FLAG);
af2fd961 779
af2fd961
GRG
780 // Incoming connection (server) or connection established (client)
781 if (result & GSOCK_CONNECTION_FLAG)
782 {
d775fa82
WS
783 m_connected = true;
784 m_establishing = false;
204b046e
KH
785 valid_result = true;
786 break;
af2fd961
GRG
787 }
788
04e1eb03 789 // Data available or output buffer ready
81b92e17 790 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
af2fd961 791 {
204b046e
KH
792 valid_result = true;
793 break;
af2fd961
GRG
794 }
795
c0043a50
GRG
796 // Connection lost
797 if (result & GSOCK_LOST_FLAG)
798 {
d775fa82
WS
799 m_connected = false;
800 m_establishing = false;
204b046e
KH
801 valid_result = ((flags & GSOCK_LOST_FLAG) != 0);
802 break;
c0043a50
GRG
803 }
804
81b92e17 805 // Wait more?
4252569b 806 long time_left = wxMilliClockToLong(time_limit - wxGetLocalTimeMillis());
204b046e 807 if ((!timeout) || (time_left <= 0) || (m_interrupt))
d775fa82 808 done = true;
d3ea6527 809 else
204b046e 810 {
8e3f3880 811 if (has_event_loop)
f01bca89
JS
812 {
813 PROCESS_EVENTS();
814 }
8e3f3880 815 else
f01bca89 816 {
204b046e
KH
817 // If there's less than 50 ms left, just call select with that timeout.
818 if (time_left < 50)
819 m_socket->SetTimeout(time_left);
f01bca89
JS
820 }
821 }
56d8adc0 822 }
f4ada568 823
204b046e 824 // Set timeout back to original value (we overwrote it for polling)
f01bca89
JS
825 if (!has_event_loop)
826 m_socket->SetTimeout(m_timeout*1000);
204b046e
KH
827
828 return valid_result;
f4ada568 829}
f4ada568 830
a737331d 831bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 832{
7fb0a11d
WS
833 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
834 GSOCK_OUTPUT_FLAG |
835 GSOCK_CONNECTION_FLAG |
836 GSOCK_LOST_FLAG);
f4ada568 837}
f4ada568 838
a737331d 839bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 840{
ef57d866 841 // Check pushback buffer before entering _Wait
96db102a 842 if (m_unread)
d775fa82 843 return true;
96db102a 844
ef57d866 845 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
90e572f1 846 // _Wait because of the semantics of WaitForRead: a return
d775fa82 847 // value of true means that a GSocket_Read call will return
ef57d866
GRG
848 // immediately, not that there is actually data to read.
849
850 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
851 GSOCK_LOST_FLAG);
f4ada568
GL
852}
853
bfa7bf7d 854
a737331d 855bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 856{
7fb0a11d 857 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
a737331d 858}
f4ada568 859
a737331d
GL
860bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
861{
7fb0a11d 862 return _Wait(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{
875 GAddress *peer;
876
877 if (!m_socket)
d775fa82 878 return false;
ef57d866 879
8b6fc577 880 peer = m_socket->GetPeer();
007c77ab
RL
881
882 // copying a null address would just trigger an assert anyway
883
884 if (!peer)
d775fa82 885 return false;
007c77ab 886
ef57d866
GRG
887 addr_man.SetAddress(peer);
888 GAddress_destroy(peer);
889
d775fa82 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{
7fb0a11d 959 m_flags = flags;
f4ada568 960}
f0a56ab0 961
f187448d 962
ef57d866 963// --------------------------------------------------------------------------
f187448d 964// Event handling
ef57d866 965// --------------------------------------------------------------------------
a324a7bc 966
bffc1eaa
GRG
967// A note on how events are processed, which is probably the most
968// difficult thing to get working right while keeping the same API
969// and functionality for all platforms.
970//
971// When GSocket detects an event, it calls wx_socket_callback, which in
972// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
973// object. OnRequest does some housekeeping, and if the event is to be
974// propagated to the user, it creates a new wxSocketEvent object and
975// posts it. The event is not processed immediately, but delayed with
976// AddPendingEvent instead. This is necessary in order to decouple the
977// event processing from wx_socket_callback; otherwise, subsequent IO
978// calls made from the user event handler would fail, as gtk callbacks
979// are not reentrant.
980//
981// Note that, unlike events, user callbacks (now deprecated) are _not_
982// decoupled from wx_socket_callback and thus they suffer from a variety
983// of problems. Avoid them where possible and use events instead.
96db102a 984
90350682
VZ
985extern "C"
986void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
987 GSocketEvent notification,
988 char *cdata)
a324a7bc 989{
7fb0a11d 990 wxSocketBase *sckobj = (wxSocketBase *)cdata;
a324a7bc 991
7fb0a11d 992 sckobj->OnRequest((wxSocketNotify) notification);
56d8adc0 993}
a324a7bc 994
bffc1eaa 995void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 996{
bffc1eaa
GRG
997 // NOTE: We duplicate some of the code in _Wait, but this doesn't
998 // hurt. It has to be here because the (GSocket) event might arrive
999 // a bit delayed, and it has to be in _Wait as well because we don't
1000 // know whether the Wait functions are being used.
ef57d866 1001
bffc1eaa 1002 switch(notification)
d80d1aba 1003 {
04e1eb03 1004 case wxSOCKET_CONNECTION:
d775fa82
WS
1005 m_establishing = false;
1006 m_connected = true;
04e1eb03
GRG
1007 break;
1008
d3ea6527
GRG
1009 // If we are in the middle of a R/W operation, do not
1010 // propagate events to users. Also, filter 'late' events
1011 // which are no longer valid.
ef57d866 1012
04e1eb03 1013 case wxSOCKET_INPUT:
8b6fc577 1014 if (m_reading || !m_socket->Select(GSOCK_INPUT_FLAG))
04e1eb03
GRG
1015 return;
1016 break;
1017
1018 case wxSOCKET_OUTPUT:
8b6fc577 1019 if (m_writing || !m_socket->Select(GSOCK_OUTPUT_FLAG))
04e1eb03
GRG
1020 return;
1021 break;
1022
1023 case wxSOCKET_LOST:
d775fa82
WS
1024 m_connected = false;
1025 m_establishing = false;
04e1eb03
GRG
1026 break;
1027
1028 default:
1029 break;
96db102a
GRG
1030 }
1031
f187448d
GRG
1032 // Schedule the event
1033
52fbdb58 1034 wxSocketEventFlags flag = 0;
999836aa 1035 wxUnusedVar(flag);
bffc1eaa 1036 switch (notification)
f187448d
GRG
1037 {
1038 case GSOCK_INPUT: flag = GSOCK_INPUT_FLAG; break;
1039 case GSOCK_OUTPUT: flag = GSOCK_OUTPUT_FLAG; break;
1040 case GSOCK_CONNECTION: flag = GSOCK_CONNECTION_FLAG; break;
1041 case GSOCK_LOST: flag = GSOCK_LOST_FLAG; break;
52fbdb58 1042 default:
5c9eff30 1043 wxLogWarning(_("wxSocket: unknown event!."));
52fbdb58 1044 return;
f187448d
GRG
1045 }
1046
bffc1eaa 1047 if (((m_eventmask & flag) == flag) && m_notify)
d80d1aba 1048 {
f187448d 1049 if (m_handler)
bffc1eaa
GRG
1050 {
1051 wxSocketEvent event(m_id);
1052 event.m_event = notification;
1053 event.m_clientData = m_clientData;
1054 event.SetEventObject(this);
1055
f187448d 1056 m_handler->AddPendingEvent(event);
bffc1eaa 1057 }
f4ada568 1058 }
f4ada568
GL
1059}
1060
f187448d
GRG
1061void wxSocketBase::Notify(bool notify)
1062{
7fb0a11d 1063 m_notify = notify;
2804f77d
VZ
1064 if (m_socket)
1065 m_socket->Notify(notify);
f187448d
GRG
1066}
1067
1068void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1069{
7fb0a11d 1070 m_eventmask = flags;
f187448d
GRG
1071}
1072
71622a7a 1073void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1074{
7fb0a11d
WS
1075 m_handler = &handler;
1076 m_id = id;
f4ada568
GL
1077}
1078
ef57d866
GRG
1079// --------------------------------------------------------------------------
1080// Pushback buffer
1081// --------------------------------------------------------------------------
db131261 1082
f187448d 1083void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1084{
dc5c1114
GRG
1085 if (!size) return;
1086
a324a7bc 1087 if (m_unread == NULL)
f187448d 1088 m_unread = malloc(size);
dc5c1114
GRG
1089 else
1090 {
f187448d 1091 void *tmp;
f4ada568 1092
f187448d
GRG
1093 tmp = malloc(m_unrd_size + size);
1094 memcpy((char *)tmp + size, m_unread, m_unrd_size);
41895a05 1095 free(m_unread);
a324a7bc
GL
1096
1097 m_unread = tmp;
41895a05 1098 }
31528cd3 1099
f4ada568 1100 m_unrd_size += size;
a324a7bc
GL
1101
1102 memcpy(m_unread, buffer, size);
f4ada568
GL
1103}
1104
f187448d 1105wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568
GL
1106{
1107 if (!m_unrd_size)
1108 return 0;
1109
a324a7bc
GL
1110 if (size > (m_unrd_size-m_unrd_cur))
1111 size = m_unrd_size-m_unrd_cur;
96db102a 1112
f187448d 1113 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1114
dc5c1114
GRG
1115 if (!peek)
1116 {
a324a7bc 1117 m_unrd_cur += size;
dc5c1114
GRG
1118 if (m_unrd_size == m_unrd_cur)
1119 {
f4ada568
GL
1120 free(m_unread);
1121 m_unread = NULL;
a324a7bc
GL
1122 m_unrd_size = 0;
1123 m_unrd_cur = 0;
f4ada568
GL
1124 }
1125 }
1126
1127 return size;
1128}
1129
f187448d 1130
ef57d866 1131// ==========================================================================
c3e646b4 1132// wxSocketServer
ef57d866 1133// ==========================================================================
f4ada568 1134
ef57d866
GRG
1135// --------------------------------------------------------------------------
1136// Ctor
1137// --------------------------------------------------------------------------
56d8adc0 1138
fbfb8bcc 1139wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
71622a7a
GRG
1140 wxSocketFlags flags)
1141 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1142{
007c77ab 1143 wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
f4ada568 1144
007c77ab 1145 m_socket = GSocket_new();
384b4373 1146
007c77ab
RL
1147 if (!m_socket)
1148 {
1149 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_new failed") );
1150 return;
1151 }
a737331d 1152
2804f77d
VZ
1153 // Setup the socket as server
1154 m_socket->Notify(m_notify);
8b6fc577 1155 m_socket->SetLocal(addr_man.GetAddress());
d775fa82 1156
74c481d1 1157 if (GetFlags() & wxSOCKET_REUSEADDR) {
8b6fc577 1158 m_socket->SetReusable();
74c481d1 1159 }
60edcf45
VZ
1160 if (GetFlags() & wxSOCKET_BROADCAST) {
1161 m_socket->SetBroadcast();
1162 }
1163 if (GetFlags() & wxSOCKET_NOBIND) {
1164 m_socket->DontDoBind();
1165 }
74c481d1 1166
8b6fc577 1167 if (m_socket->SetServer() != GSOCK_NOERROR)
007c77ab 1168 {
8b6fc577 1169 delete m_socket;
007c77ab
RL
1170 m_socket = NULL;
1171
1172 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_SetServer failed") );
1173 return;
1174 }
1175
8b6fc577
DE
1176 m_socket->SetTimeout(m_timeout * 1000);
1177 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
007c77ab
RL
1178 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1179 wx_socket_callback, (char *)this);
2804f77d
VZ
1180
1181 wxLogTrace( wxTRACE_Socket, _T("wxSocketServer on fd %d"), m_socket->m_fd );
f4ada568
GL
1182}
1183
ef57d866
GRG
1184// --------------------------------------------------------------------------
1185// Accept
1186// --------------------------------------------------------------------------
8c14576d 1187
d80d1aba 1188bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1189{
a324a7bc 1190 GSocket *child_socket;
f4ada568 1191
17aa2bec 1192 if (!m_socket)
d775fa82 1193 return false;
17aa2bec 1194
d775fa82 1195 // If wait == false, then the call should be nonblocking.
56d8adc0
GRG
1196 // When we are finished, we put the socket to blocking mode
1197 // again.
d80d1aba
GRG
1198
1199 if (!wait)
8b6fc577 1200 m_socket->SetNonBlocking(1);
d80d1aba 1201
8b6fc577 1202 child_socket = m_socket->WaitConnection();
384b4373 1203
d80d1aba 1204 if (!wait)
8b6fc577 1205 m_socket->SetNonBlocking(0);
d80d1aba 1206
04e1eb03 1207 if (!child_socket)
d775fa82 1208 return false;
d80d1aba 1209
71622a7a 1210 sock.m_type = wxSOCKET_BASE;
a324a7bc 1211 sock.m_socket = child_socket;
d775fa82 1212 sock.m_connected = true;
f4ada568 1213
8b6fc577
DE
1214 sock.m_socket->SetTimeout(sock.m_timeout * 1000);
1215 sock.m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
56d8adc0
GRG
1216 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1217 wx_socket_callback, (char *)&sock);
1218
d775fa82 1219 return true;
f4ada568
GL
1220}
1221
d80d1aba 1222wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568
GL
1223{
1224 wxSocketBase* sock = new wxSocketBase();
1225
71622a7a 1226 sock->SetFlags(m_flags);
f4ada568 1227
d80d1aba 1228 if (!AcceptWith(*sock, wait))
c3e646b4
VZ
1229 {
1230 sock->Destroy();
1231 sock = NULL;
1232 }
f4ada568 1233
f4ada568
GL
1234 return sock;
1235}
1236
17aa2bec 1237bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1238{
7fb0a11d 1239 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
d80d1aba
GRG
1240}
1241
bfa7bf7d
VZ
1242bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1243{
11734f8a
JS
1244 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1245
8b6fc577 1246 if (m_socket->GetSockOpt(level, optname, optval, optlen)
bfa7bf7d
VZ
1247 != GSOCK_NOERROR)
1248 {
d775fa82 1249 return false;
bfa7bf7d 1250 }
d775fa82 1251 return true;
bfa7bf7d
VZ
1252}
1253
37340c48 1254bool wxSocketBase::SetOption(int level, int optname, const void *optval,
bfa7bf7d
VZ
1255 int optlen)
1256{
11734f8a 1257 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
8e3f3880 1258
8b6fc577 1259 if (m_socket->SetSockOpt(level, optname, optval, optlen)
bfa7bf7d
VZ
1260 != GSOCK_NOERROR)
1261 {
d775fa82 1262 return false;
bfa7bf7d 1263 }
d775fa82 1264 return true;
bfa7bf7d
VZ
1265}
1266
72ac4e88 1267bool wxSocketBase::SetLocal(const wxIPV4address& local)
33d925b0
KH
1268{
1269 GAddress* la = local.GetAddress();
1270
30bbf68d 1271 // If the address is valid, save it for use when we call Connect
33d925b0
KH
1272 if (la && la->m_addr)
1273 {
30bbf68d 1274 m_localAddress = local;
33d925b0
KH
1275
1276 return true;
1277 }
1278
1279 return false;
1280}
1281
ef57d866 1282// ==========================================================================
8c14576d 1283// wxSocketClient
ef57d866 1284// ==========================================================================
f4ada568 1285
ef57d866
GRG
1286// --------------------------------------------------------------------------
1287// Ctor and dtor
1288// --------------------------------------------------------------------------
56d8adc0 1289
71622a7a
GRG
1290wxSocketClient::wxSocketClient(wxSocketFlags flags)
1291 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568 1292{
089b23d0
VZ
1293 m_initialRecvBufferSize =
1294 m_initialSendBufferSize = -1;
f4ada568
GL
1295}
1296
f4ada568
GL
1297wxSocketClient::~wxSocketClient()
1298{
1299}
1300
ef57d866
GRG
1301// --------------------------------------------------------------------------
1302// Connect
1303// --------------------------------------------------------------------------
dc5c1114 1304
72ac4e88
VZ
1305bool wxSocketClient::DoConnect(const wxSockAddress& addr_man,
1306 const wxSockAddress* local,
1307 bool wait)
f4ada568 1308{
791b24c4
GRG
1309 GSocketError err;
1310
ef57d866 1311 if (m_socket)
04e1eb03
GRG
1312 {
1313 // Shutdown and destroy the socket
f4ada568 1314 Close();
8b6fc577 1315 delete m_socket;
04e1eb03 1316 }
a324a7bc 1317
a324a7bc 1318 m_socket = GSocket_new();
d775fa82
WS
1319 m_connected = false;
1320 m_establishing = false;
384b4373 1321
a324a7bc 1322 if (!m_socket)
d775fa82 1323 return false;
384b4373 1324
8b6fc577
DE
1325 m_socket->SetTimeout(m_timeout * 1000);
1326 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
96db102a
GRG
1327 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1328 wx_socket_callback, (char *)this);
56d8adc0 1329
d775fa82 1330 // If wait == false, then the call should be nonblocking.
56d8adc0
GRG
1331 // When we are finished, we put the socket to blocking mode
1332 // again.
f4ada568 1333
791b24c4 1334 if (!wait)
8b6fc577 1335 m_socket->SetNonBlocking(1);
791b24c4 1336
33d925b0
KH
1337 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1338 if (GetFlags() & wxSOCKET_REUSEADDR)
1339 {
1340 m_socket->SetReusable();
1341 }
60edcf45
VZ
1342 if (GetFlags() & wxSOCKET_BROADCAST)
1343 {
1344 m_socket->SetBroadcast();
1345 }
1346 if (GetFlags() & wxSOCKET_NOBIND)
1347 {
1348 m_socket->DontDoBind();
1349 }
33d925b0 1350
30bbf68d
KH
1351 // If no local address was passed and one has been set, use the one that was Set
1352 if (!local && m_localAddress.GetAddress())
1353 {
1354 local = &m_localAddress;
1355 }
1356
33d925b0
KH
1357 // Bind to the local IP address and port, when provided
1358 if (local)
1359 {
1360 GAddress* la = local->GetAddress();
1361
1362 if (la && la->m_addr)
1363 m_socket->SetLocal(la);
1364 }
1365
8c029a5b
VZ
1366#if defined(__WXMSW__) || defined(__WXGTK__)
1367 m_socket->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
1368#endif
1369
8b6fc577
DE
1370 m_socket->SetPeer(addr_man.GetAddress());
1371 err = m_socket->Connect(GSOCK_STREAMED);
791b24c4 1372
2804f77d
VZ
1373 //this will register for callbacks - must be called after m_socket->m_fd was initialized
1374 m_socket->Notify(m_notify);
1375
791b24c4 1376 if (!wait)
8b6fc577 1377 m_socket->SetNonBlocking(0);
791b24c4
GRG
1378
1379 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1380 {
1381 if (err == GSOCK_WOULDBLOCK)
d775fa82 1382 m_establishing = true;
56d8adc0 1383
d775fa82 1384 return false;
56d8adc0 1385 }
9111db68 1386
d775fa82
WS
1387 m_connected = true;
1388 return true;
f4ada568
GL
1389}
1390
72ac4e88 1391bool wxSocketClient::Connect(const wxSockAddress& addr_man, bool wait)
33d925b0 1392{
72ac4e88 1393 return DoConnect(addr_man, NULL, wait);
33d925b0
KH
1394}
1395
72ac4e88
VZ
1396bool wxSocketClient::Connect(const wxSockAddress& addr_man,
1397 const wxSockAddress& local,
1398 bool wait)
33d925b0 1399{
72ac4e88 1400 return DoConnect(addr_man, &local, wait);
33d925b0
KH
1401}
1402
d80d1aba 1403bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1404{
7fb0a11d
WS
1405 if (m_connected) // Already connected
1406 return true;
d80d1aba 1407
7fb0a11d
WS
1408 if (!m_establishing || !m_socket) // No connection in progress
1409 return false;
d80d1aba 1410
7fb0a11d
WS
1411 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1412 GSOCK_LOST_FLAG);
f4ada568
GL
1413}
1414
ef57d866 1415// ==========================================================================
dc5c1114 1416// wxDatagramSocket
ef57d866 1417// ==========================================================================
dc5c1114
GRG
1418
1419/* NOTE: experimental stuff - might change */
1420
fbfb8bcc 1421wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
1422 wxSocketFlags flags )
1423 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114 1424{
7fb0a11d
WS
1425 // Create the socket
1426 m_socket = GSocket_new();
dc5c1114 1427
28bf2f3c 1428 if (!m_socket)
7fb0a11d
WS
1429 {
1430 wxFAIL_MSG( _T("datagram socket not new'd") );
1431 return;
1432 }
2804f77d 1433 m_socket->Notify(m_notify);
7fb0a11d
WS
1434 // Setup the socket as non connection oriented
1435 m_socket->SetLocal(addr.GetAddress());
28bf2f3c
VZ
1436 if (flags & wxSOCKET_REUSEADDR)
1437 {
1438 m_socket->SetReusable();
1439 }
60edcf45
VZ
1440 if (GetFlags() & wxSOCKET_BROADCAST)
1441 {
1442 m_socket->SetBroadcast();
1443 }
1444 if (GetFlags() & wxSOCKET_NOBIND)
1445 {
1446 m_socket->DontDoBind();
1447 }
28bf2f3c 1448 if ( m_socket->SetNonOriented() != GSOCK_NOERROR )
7fb0a11d
WS
1449 {
1450 delete m_socket;
1451 m_socket = NULL;
1452 return;
1453 }
dc5c1114 1454
7fb0a11d
WS
1455 // Initialize all stuff
1456 m_connected = false;
1457 m_establishing = false;
1458 m_socket->SetTimeout( m_timeout );
1459 m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1460 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1461 wx_socket_callback, (char*)this );
dc5c1114
GRG
1462}
1463
1464wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 1465 void* buf,
dc5c1114
GRG
1466 wxUint32 nBytes )
1467{
1468 Read(buf, nBytes);
1469 GetPeer(addr);
1470 return (*this);
1471}
1472
fbfb8bcc 1473wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 1474 const void* buf,
dc5c1114
GRG
1475 wxUint32 nBytes )
1476{
11734f8a 1477 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
8e3f3880 1478
8b6fc577 1479 m_socket->SetPeer(addr.GetAddress());
dc5c1114
GRG
1480 Write(buf, nBytes);
1481 return (*this);
1482}
1483
ef57d866 1484// ==========================================================================
a58d5df4 1485// wxSocketModule
ef57d866 1486// ==========================================================================
dc5c1114 1487
ed4c6c69 1488class wxSocketModule : public wxModule
dc5c1114 1489{
dc5c1114 1490public:
6c0d0845
VZ
1491 virtual bool OnInit()
1492 {
1493 // wxSocketBase will call GSocket_Init() itself when/if needed
d775fa82 1494 return true;
6c0d0845
VZ
1495 }
1496
1497 virtual void OnExit()
1498 {
1499 if ( wxSocketBase::IsInitialized() )
1500 wxSocketBase::Shutdown();
1501 }
1502
1503private:
1504 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
1505};
1506
1507IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1508
35a4dab7
GL
1509#endif
1510 // wxUSE_SOCKETS