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