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