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