]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
check better before overwriting files (patch 951868)
[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"
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
VZ
100
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#ifdef __WXMSW__
126 /*
127 The following asserting might be neccessary for linux as well,
128 but I cannot verify this.
129 */
130 wxASSERT(wxThread::IsMain(),
131 wxT("To use sockets in a secondary thread, ")
132 wxT("call wxSocketBase::Initialize() from the main thread."));
133 /*
134 Details: Initialize() creates a hidden window as a sink for socket
135 events, such as 'read completed'. wxMSW has only one message loop
136 for the main thread. If Initialize is called in a secondary thread,
137 the socket window will be created for the secondary thread, but
138 since there is no message loop on this thread, it will never
139 receive events and all socket operations will time out.
140 BTW, the main thread must not be stopped using sleep or block
141 on a semaphore (a bad idea in any case) or socket operations
142 will time out.
143 */
144#endif
38bb138f
VS
145 wxAppTraits *traits = wxAppConsole::GetInstance() ?
146 wxAppConsole::GetInstance()->GetTraits() : NULL;
147 GSocketGUIFunctionsTable *functions =
148 traits ? traits->GetSocketGUIFunctionsTable() : NULL;
149 GSocket_SetGUIFunctions(functions);
150
6c0d0845
VZ
151 if ( !GSocket_Init() )
152 {
153 m_countInit--;
154
155 return FALSE;
156 }
157 }
158
159 return TRUE;
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 =
187 m_error = FALSE;
188 m_lcount = 0;
189 m_timeout = 600;
190 m_beingDeleted = FALSE;
191
192 // pushback buffer
193 m_unread = NULL;
194 m_unrd_size = 0;
195 m_unrd_cur = 0;
196
197 // events
71622a7a 198 m_id = -1;
f187448d
GRG
199 m_handler = NULL;
200 m_clientData = NULL;
bffc1eaa
GRG
201 m_notify = FALSE;
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
GL
238 if (m_socket)
239 GSocket_destroy(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.
ef57d866 251 m_beingDeleted = TRUE;
9181a383
GRG
252
253 // Shutdown and close the socket
ef57d866
GRG
254 Close();
255
bffc1eaa
GRG
256 // Supress events from now on
257 Notify(FALSE);
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
GRG
271
272 return TRUE;
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
GRG
291 // Disable callbacks
292 GSocket_UnsetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
293 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
f4ada568 294
56d8adc0 295 // Shutdown the connection
a324a7bc 296 GSocket_Shutdown(m_socket);
f4ada568
GL
297 }
298
ef57d866 299 m_connected = FALSE;
04e1eb03 300 m_establishing = FALSE;
f4ada568
GL
301 return TRUE;
302}
303
f187448d 304wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 305{
96db102a
GRG
306 // Mask read events
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
96db102a 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
96db102a
GRG
328 total = GetPushback(buffer, nbytes, FALSE);
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 {
5c9eff30 350 GSocket_SetNonBlocking(m_socket, 1);
f187448d 351 ret = GSocket_Read(m_socket, (char *)buffer, nbytes);
5c9eff30 352 GSocket_SetNonBlocking(m_socket, 0);
af2fd961
GRG
353
354 if (ret > 0)
96db102a 355 total += ret;
af2fd961 356 }
5c9eff30 357 else
56d8adc0 358 {
5c9eff30
GRG
359 bool more = TRUE;
360
361 while (more)
56d8adc0 362 {
5c9eff30
GRG
363 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
364 break;
81b92e17 365
f187448d 366 ret = GSocket_Read(m_socket, (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
GRG
397 // Mask read events
398 m_reading = TRUE;
062c4861 399
96db102a
GRG
400 total = 0;
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
GRG
473 // everything was OK
474 error = FALSE;
475
476exit:
477 m_error = error;
478 m_lcount = total;
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
GRG
487 // Mask read events
488 m_reading = TRUE;
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
96db102a 500 m_reading = FALSE;
f4ada568
GL
501
502 return *this;
503}
504
f187448d 505wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 506{
96db102a
GRG
507 // Mask write events
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
96db102a
GRG
519 m_writing = FALSE;
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 {
5c9eff30 541 GSocket_SetNonBlocking(m_socket, 1);
f187448d 542 ret = GSocket_Write(m_socket, (const char *)buffer, nbytes);
5c9eff30 543 GSocket_SetNonBlocking(m_socket, 0);
af2fd961
GRG
544
545 if (ret > 0)
96db102a 546 total = ret;
af2fd961 547 }
5c9eff30 548 else
56d8adc0 549 {
5c9eff30
GRG
550 bool more = TRUE;
551
c3e646b4 552 while (more)
56d8adc0 553 {
5c9eff30
GRG
554 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
555 break;
81b92e17 556
f187448d 557 ret = GSocket_Write(m_socket, (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
GRG
587 // Mask write events
588 m_writing = TRUE;
589
590 error = TRUE;
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
GRG
621 // everything was OK
622 error = FALSE;
623
624exit:
625 m_error = error;
626 m_lcount = total;
627 m_writing = FALSE;
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
96db102a
GRG
637 m_error = FALSE;
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
GRG
649 // Mask read events
650 m_reading = TRUE;
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;
04e1eb03 663 m_error = FALSE;
17aa2bec 664
dc5c1114 665 // Allow read events again
96db102a
GRG
666 m_reading = FALSE;
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
81b92e17
GRG
688 // Set this to TRUE to interrupt ongoing waits
689 m_interrupt = FALSE;
690
ef57d866 691 // Check for valid socket
af2fd961
GRG
692 if (!m_socket)
693 return FALSE;
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
JS
701#if !defined(wxUSE_GUI) || !wxUSE_GUI
702 GSocket_SetTimeout(m_socket, timeout);
703#endif
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
GRG
715 wxStopWatch chrono;
716 bool done = FALSE;
717
718 while (!done)
56d8adc0 719 {
af2fd961
GRG
720 result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG);
721
af2fd961
GRG
722 // Incoming connection (server) or connection established (client)
723 if (result & GSOCK_CONNECTION_FLAG)
724 {
af2fd961
GRG
725 m_connected = TRUE;
726 m_establishing = FALSE;
727 return TRUE;
728 }
729
04e1eb03 730 // Data available or output buffer ready
81b92e17 731 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
af2fd961 732 {
81b92e17 733 return TRUE;
af2fd961
GRG
734 }
735
c0043a50
GRG
736 // Connection lost
737 if (result & GSOCK_LOST_FLAG)
738 {
ef57d866 739 m_connected = FALSE;
04e1eb03 740 m_establishing = FALSE;
378d2bd3 741 return (flags & GSOCK_LOST_FLAG) != 0;
c0043a50
GRG
742 }
743
81b92e17 744 // Wait more?
71622a7a
GRG
745 if ((!timeout) || (chrono.Time() > timeout) || (m_interrupt))
746 done = TRUE;
d3ea6527
GRG
747 else
748 PROCESS_EVENTS();
56d8adc0 749 }
f4ada568 750
af2fd961 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
GRG
765 if (m_unread)
766 return TRUE;
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
770 // value of TRUE means that a GSocket_Read call will return
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)
801 return FALSE;
802
803 peer = GSocket_GetPeer(m_socket);
007c77ab
RL
804
805 // copying a null address would just trigger an assert anyway
806
807 if (!peer)
808 return FALSE;
809
ef57d866
GRG
810 addr_man.SetAddress(peer);
811 GAddress_destroy(peer);
812
813 return TRUE;
814}
815
816bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
817{
818 GAddress *local;
819
820 if (!m_socket)
821 return FALSE;
822
823 local = GSocket_GetLocal(m_socket);
824 addr_man.SetAddress(local);
825 GAddress_destroy(local);
826
827 return TRUE;
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;
a3bf7524 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)
e8f4c584 877 GSocket_SetTimeout(m_socket, 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
GRG
927 case wxSOCKET_CONNECTION:
928 m_establishing = FALSE;
929 m_connected = TRUE;
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
GRG
936 case wxSOCKET_INPUT:
937 if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
938 return;
939 break;
940
941 case wxSOCKET_OUTPUT:
942 if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
943 return;
944 break;
945
946 case wxSOCKET_LOST:
947 m_connected = FALSE;
948 m_establishing = FALSE;
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
007c77ab
RL
1076 GSocket_SetLocal(m_socket, addr_man.GetAddress());
1077 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
1078 {
1079 GSocket_destroy(m_socket);
1080 m_socket = NULL;
1081
1082 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_SetServer failed") );
1083 return;
1084 }
1085
1086 GSocket_SetTimeout(m_socket, m_timeout * 1000);
1087 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1088 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1089 wx_socket_callback, (char *)this);
f4ada568
GL
1090}
1091
ef57d866
GRG
1092// --------------------------------------------------------------------------
1093// Accept
1094// --------------------------------------------------------------------------
8c14576d 1095
d80d1aba 1096bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1097{
a324a7bc 1098 GSocket *child_socket;
f4ada568 1099
17aa2bec
GRG
1100 if (!m_socket)
1101 return FALSE;
1102
04e1eb03 1103 // If wait == FALSE, then the call should be nonblocking.
56d8adc0
GRG
1104 // When we are finished, we put the socket to blocking mode
1105 // again.
d80d1aba
GRG
1106
1107 if (!wait)
5c9eff30 1108 GSocket_SetNonBlocking(m_socket, 1);
d80d1aba 1109
a324a7bc 1110 child_socket = GSocket_WaitConnection(m_socket);
384b4373 1111
d80d1aba 1112 if (!wait)
5c9eff30 1113 GSocket_SetNonBlocking(m_socket, 0);
d80d1aba 1114
04e1eb03 1115 if (!child_socket)
d80d1aba
GRG
1116 return FALSE;
1117
71622a7a 1118 sock.m_type = wxSOCKET_BASE;
a324a7bc 1119 sock.m_socket = child_socket;
f4ada568
GL
1120 sock.m_connected = TRUE;
1121
e8f4c584 1122 GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
56d8adc0
GRG
1123 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1124 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1125 wx_socket_callback, (char *)&sock);
1126
f4ada568
GL
1127 return TRUE;
1128}
1129
d80d1aba 1130wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568
GL
1131{
1132 wxSocketBase* sock = new wxSocketBase();
1133
71622a7a 1134 sock->SetFlags(m_flags);
f4ada568 1135
d80d1aba 1136 if (!AcceptWith(*sock, wait))
c3e646b4
VZ
1137 {
1138 sock->Destroy();
1139 sock = NULL;
1140 }
f4ada568 1141
f4ada568
GL
1142 return sock;
1143}
1144
17aa2bec 1145bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1146{
af2fd961 1147 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
d80d1aba
GRG
1148}
1149
bfa7bf7d
VZ
1150bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1151{
1152 if (GSocket_GetSockOpt(m_socket, level, optname, optval, optlen)
1153 != GSOCK_NOERROR)
1154 {
1155 return FALSE;
1156 }
1157 return TRUE;
1158}
1159
1160bool wxSocketBase::SetOption(int level, int optname, const void *optval,
1161 int optlen)
1162{
1163 if (GSocket_SetSockOpt(m_socket, level, optname, optval, optlen)
1164 != GSOCK_NOERROR)
1165 {
1166 return FALSE;
1167 }
1168 return TRUE;
1169}
1170
ef57d866 1171// ==========================================================================
8c14576d 1172// wxSocketClient
ef57d866 1173// ==========================================================================
f4ada568 1174
ef57d866
GRG
1175// --------------------------------------------------------------------------
1176// Ctor and dtor
1177// --------------------------------------------------------------------------
56d8adc0 1178
71622a7a
GRG
1179wxSocketClient::wxSocketClient(wxSocketFlags flags)
1180 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568
GL
1181{
1182}
1183
f4ada568
GL
1184wxSocketClient::~wxSocketClient()
1185{
1186}
1187
ef57d866
GRG
1188// --------------------------------------------------------------------------
1189// Connect
1190// --------------------------------------------------------------------------
dc5c1114 1191
791b24c4 1192bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
f4ada568 1193{
791b24c4
GRG
1194 GSocketError err;
1195
ef57d866 1196 if (m_socket)
04e1eb03
GRG
1197 {
1198 // Shutdown and destroy the socket
f4ada568 1199 Close();
a324a7bc 1200 GSocket_destroy(m_socket);
04e1eb03 1201 }
a324a7bc 1202
a324a7bc 1203 m_socket = GSocket_new();
d80d1aba
GRG
1204 m_connected = FALSE;
1205 m_establishing = FALSE;
384b4373 1206
a324a7bc 1207 if (!m_socket)
f4ada568 1208 return FALSE;
384b4373 1209
e8f4c584 1210 GSocket_SetTimeout(m_socket, m_timeout * 1000);
96db102a
GRG
1211 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1212 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1213 wx_socket_callback, (char *)this);
56d8adc0 1214
04e1eb03 1215 // If wait == FALSE, then the call should be nonblocking.
56d8adc0
GRG
1216 // When we are finished, we put the socket to blocking mode
1217 // again.
f4ada568 1218
791b24c4 1219 if (!wait)
5c9eff30 1220 GSocket_SetNonBlocking(m_socket, 1);
791b24c4 1221
a324a7bc 1222 GSocket_SetPeer(m_socket, addr_man.GetAddress());
791b24c4
GRG
1223 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
1224
1225 if (!wait)
5c9eff30 1226 GSocket_SetNonBlocking(m_socket, 0);
791b24c4
GRG
1227
1228 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1229 {
1230 if (err == GSOCK_WOULDBLOCK)
1231 m_establishing = TRUE;
1232
f4ada568 1233 return FALSE;
56d8adc0 1234 }
9111db68 1235
f4ada568
GL
1236 m_connected = TRUE;
1237 return TRUE;
1238}
1239
d80d1aba 1240bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1241{
af2fd961 1242 if (m_connected) // Already connected
d80d1aba
GRG
1243 return TRUE;
1244
af2fd961 1245 if (!m_establishing || !m_socket) // No connection in progress
d80d1aba
GRG
1246 return FALSE;
1247
2b396caa
GRG
1248 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1249 GSOCK_LOST_FLAG);
f4ada568
GL
1250}
1251
ef57d866 1252// ==========================================================================
dc5c1114 1253// wxDatagramSocket
ef57d866 1254// ==========================================================================
dc5c1114
GRG
1255
1256/* NOTE: experimental stuff - might change */
1257
71622a7a
GRG
1258wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr,
1259 wxSocketFlags flags )
1260 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114
GRG
1261{
1262 // Create the socket
1263 m_socket = GSocket_new();
1264
1265 if(!m_socket)
bfa7bf7d
VZ
1266 {
1267 wxASSERT_MSG( 0, _T("datagram socket not new'd") );
dc5c1114 1268 return;
bfa7bf7d 1269 }
dc5c1114 1270 // Setup the socket as non connection oriented
bfa7bf7d 1271 GSocket_Unstreamed(m_socket);
dc5c1114
GRG
1272 GSocket_SetLocal(m_socket, addr.GetAddress());
1273 if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
1274 {
1275 GSocket_destroy(m_socket);
1276 m_socket = NULL;
1277 return;
1278 }
1279
1280 // Initialize all stuff
1281 m_connected = FALSE;
1282 m_establishing = FALSE;
1283 GSocket_SetTimeout( m_socket, m_timeout );
1284 GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1285 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1286 wx_socket_callback, (char*)this );
1287
1288}
1289
1290wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 1291 void* buf,
dc5c1114
GRG
1292 wxUint32 nBytes )
1293{
1294 Read(buf, nBytes);
1295 GetPeer(addr);
1296 return (*this);
1297}
1298
1299wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
f187448d 1300 const void* buf,
dc5c1114
GRG
1301 wxUint32 nBytes )
1302{
1303 GSocket_SetPeer(m_socket, addr.GetAddress());
1304 Write(buf, nBytes);
1305 return (*this);
1306}
1307
ef57d866 1308// ==========================================================================
a58d5df4 1309// wxSocketModule
ef57d866 1310// ==========================================================================
dc5c1114 1311
ed4c6c69 1312class wxSocketModule : public wxModule
dc5c1114 1313{
dc5c1114 1314public:
6c0d0845
VZ
1315 virtual bool OnInit()
1316 {
1317 // wxSocketBase will call GSocket_Init() itself when/if needed
1318 return TRUE;
1319 }
1320
1321 virtual void OnExit()
1322 {
1323 if ( wxSocketBase::IsInitialized() )
1324 wxSocketBase::Shutdown();
1325 }
1326
1327private:
1328 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
1329};
1330
1331IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1332
35a4dab7
GL
1333#endif
1334 // wxUSE_SOCKETS
007c77ab
RL
1335
1336// vi:sts=4:sw=4:et