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