]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
typo fixed
[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
9fea1a5d 866static void LINKAGEMODE wx_socket_callback(GSocket *socket, GSocketEvent event, char *cdata)
a324a7bc
GL
867{
868 wxSocketBase *sckobj = (wxSocketBase *)cdata;
869
aa8fb7a0 870 sckobj->OnRequest((wxSocketNotify)event);
a324a7bc
GL
871}
872
56d8adc0 873wxSocketEventFlags wxSocketBase::EventToNotify(wxSocketNotify evt)
f4ada568 874{
56d8adc0
GRG
875 switch (evt)
876 {
877 case GSOCK_INPUT: return GSOCK_INPUT_FLAG;
878 case GSOCK_OUTPUT: return GSOCK_OUTPUT_FLAG;
879 case GSOCK_CONNECTION: return GSOCK_CONNECTION_FLAG;
880 case GSOCK_LOST: return GSOCK_LOST_FLAG;
881 }
882 return 0;
883}
aadbdf11 884
56d8adc0
GRG
885void wxSocketBase::SetNotify(wxSocketEventFlags flags)
886{
887 m_neededreq = flags;
888}
a324a7bc 889
56d8adc0
GRG
890void wxSocketBase::Notify(bool notify)
891{
892 m_notify_state = notify;
f4ada568
GL
893}
894
aa8fb7a0 895void wxSocketBase::OnRequest(wxSocketNotify req_evt)
f4ada568 896{
a737331d 897 wxSocketEvent event(m_id);
56d8adc0 898 wxSocketEventFlags flag = EventToNotify(req_evt);
a324a7bc 899
af2fd961
GRG
900 // NOTE: this duplicates some of the code in _Wait (lost
901 // connection and connection establishment handling) but
902 // this doesn't hurt. It has to be here because maybe the
903 // WaitXXX are not being used, and it has to be in _Wait
904 // as well because the event might be a bit delayed.
905 //
d80d1aba
GRG
906 switch(req_evt)
907 {
908 case wxSOCKET_CONNECTION:
909 m_establishing = FALSE;
910 m_connected = TRUE;
911 break;
912 case wxSOCKET_LOST:
56d8adc0 913 m_defer_buffer = NULL;
d80d1aba
GRG
914 Close();
915 break;
916 case wxSOCKET_INPUT:
917 case wxSOCKET_OUTPUT:
56d8adc0 918 if (m_defer_buffer)
d80d1aba 919 {
56d8adc0
GRG
920 // GRG: DoDefer() no longer needs to know which
921 // event occured, because this was only used to
922 // catch LOST events and set m_defer_buffer to
923 // NULL, and this is done in OnRequest() now.
924 DoDefer();
d80d1aba
GRG
925 // Do not notify to user
926 return;
927 }
928 break;
a324a7bc 929 }
f4ada568 930
56d8adc0 931 if (((m_neededreq & flag) == flag) && m_notify_state)
d80d1aba 932 {
a737331d 933 event.m_socket = this;
de3131e7 934 event.m_skevt = req_evt;
a737331d 935 ProcessEvent(event);
a324a7bc 936 OldOnNotify(req_evt);
56d8adc0
GRG
937
938 if (m_cbk)
939 m_cbk(*this, req_evt, m_cdata);
f4ada568 940 }
f4ada568
GL
941}
942
aa8fb7a0 943void wxSocketBase::OldOnNotify(wxSocketNotify evt)
f4ada568 944{
f4ada568
GL
945}
946
a737331d 947// --------------------------------------------------------------
56d8adc0 948// wxSocketBase set event handler
a737331d 949// --------------------------------------------------------------
f4ada568
GL
950
951void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
952{
953 SetNextHandler(&h_evt);
954 m_id = id;
955}
956
957// --------------------------------------------------------------
56d8adc0 958// wxSocketBase pushback library
f4ada568 959// --------------------------------------------------------------
db131261 960
aa6d9706 961void wxSocketBase::CreatePushbackAfter(const char *buffer, wxUint32 size)
f4ada568
GL
962{
963 char *curr_pos;
964
375abe3d
GL
965 if (m_unread != NULL)
966 m_unread = (char *) realloc(m_unread, m_unrd_size+size);
967 else
968 m_unread = (char *) malloc(size);
a324a7bc 969
f4ada568
GL
970 curr_pos = m_unread + m_unrd_size;
971
972 memcpy(curr_pos, buffer, size);
973 m_unrd_size += size;
974}
975
aa6d9706 976void wxSocketBase::CreatePushbackBefore(const char *buffer, wxUint32 size)
f4ada568 977{
a324a7bc
GL
978 if (m_unread == NULL)
979 m_unread = (char *)malloc(size);
980 else {
981 char *tmp;
f4ada568 982
a324a7bc
GL
983 tmp = (char *)malloc(m_unrd_size + size);
984 memcpy(tmp+size, m_unread, m_unrd_size);
41895a05 985 free(m_unread);
a324a7bc
GL
986
987 m_unread = tmp;
41895a05 988 }
31528cd3 989
f4ada568 990 m_unrd_size += size;
a324a7bc
GL
991
992 memcpy(m_unread, buffer, size);
f4ada568
GL
993}
994
aa6d9706 995wxUint32 wxSocketBase::GetPushback(char *buffer, wxUint32 size, bool peek)
f4ada568
GL
996{
997 if (!m_unrd_size)
998 return 0;
999
a324a7bc
GL
1000 if (size > (m_unrd_size-m_unrd_cur))
1001 size = m_unrd_size-m_unrd_cur;
1002 memcpy(buffer, (m_unread+m_unrd_cur), size);
f4ada568
GL
1003
1004 if (!peek) {
a324a7bc
GL
1005 m_unrd_cur += size;
1006 if (m_unrd_size == m_unrd_cur) {
f4ada568
GL
1007 free(m_unread);
1008 m_unread = NULL;
a324a7bc
GL
1009 m_unrd_size = 0;
1010 m_unrd_cur = 0;
f4ada568
GL
1011 }
1012 }
1013
1014 return size;
1015}
1016
f4ada568 1017// --------------------------------------------------------------
8c14576d 1018// wxSocketServer
f4ada568
GL
1019// --------------------------------------------------------------
1020
56d8adc0
GRG
1021// --------------------------------------------------------------
1022// wxSocketServer ctor and dtor
1023// --------------------------------------------------------------
1024
f4ada568 1025wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
17dff81c 1026 wxSockFlags flags) :
f4ada568
GL
1027 wxSocketBase(flags, SOCK_SERVER)
1028{
56d8adc0 1029 // Create the socket
a324a7bc 1030 m_socket = GSocket_new();
f4ada568 1031
a324a7bc 1032 if (!m_socket)
f4ada568 1033 return;
384b4373 1034
56d8adc0 1035 // Setup the socket as server
a324a7bc 1036 GSocket_SetLocal(m_socket, addr_man.GetAddress());
56d8adc0
GRG
1037 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
1038 {
a324a7bc
GL
1039 GSocket_destroy(m_socket);
1040 m_socket = NULL;
f4ada568
GL
1041 return;
1042 }
a737331d 1043
56d8adc0
GRG
1044 GSocket_SetTimeout(m_socket, m_timeout);
1045 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1046 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1047 wx_socket_callback, (char *)this);
1048
f4ada568
GL
1049}
1050
1051// --------------------------------------------------------------
8c14576d 1052// wxSocketServer Accept
f4ada568 1053// --------------------------------------------------------------
8c14576d 1054
d80d1aba 1055bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1056{
a324a7bc 1057 GSocket *child_socket;
f4ada568 1058
17aa2bec
GRG
1059 if (!m_socket)
1060 return FALSE;
1061
56d8adc0
GRG
1062 // GRG: If wait == FALSE, then the call should be nonblocking.
1063 // When we are finished, we put the socket to blocking mode
1064 // again.
d80d1aba
GRG
1065
1066 if (!wait)
1067 GSocket_SetNonBlocking(m_socket, TRUE);
1068
a324a7bc 1069 child_socket = GSocket_WaitConnection(m_socket);
384b4373 1070
d80d1aba
GRG
1071 if (!wait)
1072 GSocket_SetNonBlocking(m_socket, FALSE);
1073
1074 // GRG: this was not being handled!
1075 if (child_socket == NULL)
1076 return FALSE;
1077
f4ada568 1078 sock.m_type = SOCK_INTERNAL;
a324a7bc 1079 sock.m_socket = child_socket;
f4ada568
GL
1080 sock.m_connected = TRUE;
1081
56d8adc0
GRG
1082 GSocket_SetTimeout(sock.m_socket, sock.m_timeout);
1083 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1084 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1085 wx_socket_callback, (char *)&sock);
1086
f4ada568
GL
1087 return TRUE;
1088}
1089
d80d1aba 1090wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568
GL
1091{
1092 wxSocketBase* sock = new wxSocketBase();
1093
1094 sock->SetFlags((wxSockFlags)m_flags);
1095
d80d1aba 1096 if (!AcceptWith(*sock, wait))
f4ada568
GL
1097 return NULL;
1098
f4ada568
GL
1099 return sock;
1100}
1101
17aa2bec 1102bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1103{
af2fd961 1104 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
d80d1aba
GRG
1105}
1106
f4ada568 1107// --------------------------------------------------------------
8c14576d 1108// wxSocketClient
f4ada568
GL
1109// --------------------------------------------------------------
1110
f4ada568 1111// --------------------------------------------------------------
56d8adc0
GRG
1112// wxSocketClient ctor and dtor
1113// --------------------------------------------------------------
1114
f4ada568 1115wxSocketClient::wxSocketClient(wxSockFlags _flags) :
17dff81c 1116 wxSocketBase(_flags, SOCK_CLIENT)
f4ada568
GL
1117{
1118}
1119
f4ada568
GL
1120wxSocketClient::~wxSocketClient()
1121{
1122}
1123
1124// --------------------------------------------------------------
56d8adc0 1125// wxSocketClient Connect functions
f4ada568 1126// --------------------------------------------------------------
791b24c4 1127bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
f4ada568 1128{
791b24c4
GRG
1129 GSocketError err;
1130
f4ada568
GL
1131 if (IsConnected())
1132 Close();
1133
a324a7bc
GL
1134 // This should never happen.
1135 if (m_socket)
1136 GSocket_destroy(m_socket);
1137
56d8adc0 1138 // Initialize all socket stuff ...
a324a7bc 1139 m_socket = GSocket_new();
d80d1aba
GRG
1140 m_connected = FALSE;
1141 m_establishing = FALSE;
384b4373 1142
a324a7bc 1143 if (!m_socket)
f4ada568 1144 return FALSE;
384b4373 1145
56d8adc0
GRG
1146 GSocket_SetTimeout(m_socket, m_timeout);
1147
1148 // GRG: If wait == FALSE, then the call should be nonblocking.
1149 // When we are finished, we put the socket to blocking mode
1150 // again.
f4ada568 1151
791b24c4
GRG
1152 if (!wait)
1153 GSocket_SetNonBlocking(m_socket, TRUE);
1154
a324a7bc 1155 GSocket_SetPeer(m_socket, addr_man.GetAddress());
791b24c4 1156 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
56d8adc0
GRG
1157 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1158 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1159 wx_socket_callback, (char *)this);
791b24c4
GRG
1160
1161 if (!wait)
1162 GSocket_SetNonBlocking(m_socket, FALSE);
1163
1164 if (err != GSOCK_NOERROR)
56d8adc0
GRG
1165 {
1166 if (err == GSOCK_WOULDBLOCK)
1167 m_establishing = TRUE;
1168
f4ada568 1169 return FALSE;
56d8adc0 1170 }
9111db68 1171
f4ada568
GL
1172 m_connected = TRUE;
1173 return TRUE;
1174}
1175
d80d1aba 1176bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1177{
af2fd961 1178 if (m_connected) // Already connected
d80d1aba
GRG
1179 return TRUE;
1180
af2fd961 1181 if (!m_establishing || !m_socket) // No connection in progress
d80d1aba
GRG
1182 return FALSE;
1183
af2fd961 1184 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
f4ada568
GL
1185}
1186
f4ada568 1187// --------------------------------------------------------------
a324a7bc 1188// wxSocketEvent
f4ada568 1189// --------------------------------------------------------------
f4ada568 1190
a324a7bc
GL
1191wxSocketEvent::wxSocketEvent(int id)
1192 : wxEvent(id)
f4ada568 1193{
a324a7bc 1194 wxEventType type = (wxEventType)wxEVT_SOCKET;
f4ada568 1195
a324a7bc 1196 SetEventType(type);
f4ada568
GL
1197}
1198
a324a7bc 1199void wxSocketEvent::CopyObject(wxObject& obj_d) const
f4ada568 1200{
a324a7bc 1201 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
f4ada568 1202
a324a7bc 1203 wxEvent::CopyObject(obj_d);
3b4183d8 1204
a324a7bc
GL
1205 event->m_skevt = m_skevt;
1206 event->m_socket = m_socket;
3b4183d8
GL
1207}
1208
a58d5df4
GL
1209// --------------------------------------------------------------------------
1210// wxSocketModule
1211// --------------------------------------------------------------------------
1212class WXDLLEXPORT wxSocketModule: public wxModule {
1213 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1214 public:
1215 bool OnInit() {
31989b0b 1216 return GSocket_Init();
a58d5df4
GL
1217 }
1218 void OnExit() {
ca17eff3 1219 GSocket_Cleanup();
a58d5df4
GL
1220 }
1221};
1222
1223IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1224
35a4dab7
GL
1225#endif
1226 // wxUSE_SOCKETS