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