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