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