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