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