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