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