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