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