]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/gsocket.cpp
don't overwrite the existing local file if we failed to open it but it does exist
[wxWidgets.git] / src / msw / gsocket.cpp
... / ...
CommitLineData
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket)
3 * Name: src/msw/gsocket.cpp
4 * Copyright: (c) Guilhem Lavaux
5 * Licence: wxWindows Licence
6 * Author: Guillermo Rodriguez Garcia <guille@iies.es>
7 * Purpose: GSocket main MSW file
8 * Licence: The wxWindows licence
9 * CVSID: $Id$
10 * -------------------------------------------------------------------------
11 */
12
13// For compilers that support precompilation, includes "wx.h".
14#include "wx/wxprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#ifdef _MSC_VER
21 /* RPCNOTIFICATION_ROUTINE in rasasync.h (included from winsock.h),
22 * warning: conditional expression is constant.
23 */
24# pragma warning(disable:4115)
25 /* FD_SET,
26 * warning: named type definition in parentheses.
27 */
28# pragma warning(disable:4127)
29 /* GAddress_UNIX_GetPath,
30 * warning: unreferenced formal parameter.
31 */
32# pragma warning(disable:4100)
33
34#ifdef __WXWINCE__
35 /* windows.h results in tons of warnings at max warning level */
36# ifdef _MSC_VER
37# pragma warning(push, 1)
38# endif
39# include <windows.h>
40# ifdef _MSC_VER
41# pragma warning(pop)
42# pragma warning(disable:4514)
43# endif
44#endif
45
46#endif /* _MSC_VER */
47
48#if defined(__CYGWIN__)
49 //CYGWIN gives annoying warning about runtime stuff if we don't do this
50# define USE_SYS_TYPES_FD_SET
51# include <sys/types.h>
52#endif
53
54#include <winsock.h>
55
56#ifndef __GSOCKET_STANDALONE__
57# include "wx/platform.h"
58#endif
59
60#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
61
62#ifndef __GSOCKET_STANDALONE__
63# include "wx/msw/gsockmsw.h"
64# include "wx/gsocket.h"
65#else
66# include "gsockmsw.h"
67# include "gsocket.h"
68#endif /* __GSOCKET_STANDALONE__ */
69
70#ifndef __WXWINCE__
71#include <assert.h>
72#else
73#define assert(x)
74#ifndef isdigit
75#define isdigit(x) (x > 47 && x < 58)
76#endif
77#include "wx/msw/wince/net.h"
78#endif
79
80#include <string.h>
81#include <stdio.h>
82#include <stdlib.h>
83#include <stddef.h>
84#include <ctype.h>
85
86/* if we use configure for MSW WX_SOCKLEN_T will be already defined */
87#ifndef WX_SOCKLEN_T
88# define WX_SOCKLEN_T int
89#endif
90
91/* Table of GUI-related functions. We must call them indirectly because
92 * of wxBase and GUI separation: */
93
94static GSocketGUIFunctionsTable *gs_gui_functions;
95
96class GSocketGUIFunctionsTableNull: public GSocketGUIFunctionsTable
97{
98public:
99 virtual bool OnInit();
100 virtual void OnExit();
101 virtual bool CanUseEventLoop();
102 virtual bool Init_Socket(GSocket *socket);
103 virtual void Destroy_Socket(GSocket *socket);
104 virtual void Enable_Events(GSocket *socket);
105 virtual void Disable_Events(GSocket *socket);
106};
107
108bool GSocketGUIFunctionsTableNull::OnInit()
109{ return true; }
110void GSocketGUIFunctionsTableNull::OnExit()
111{}
112bool GSocketGUIFunctionsTableNull::CanUseEventLoop()
113{ return false; }
114bool GSocketGUIFunctionsTableNull::Init_Socket(GSocket *WXUNUSED(socket))
115{ return true; }
116void GSocketGUIFunctionsTableNull::Destroy_Socket(GSocket *WXUNUSED(socket))
117{}
118void GSocketGUIFunctionsTableNull::Enable_Events(GSocket *WXUNUSED(socket))
119{}
120void GSocketGUIFunctionsTableNull::Disable_Events(GSocket *WXUNUSED(socket))
121{}
122/* Global initialisers */
123
124void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable *guifunc)
125{
126 gs_gui_functions = guifunc;
127}
128
129int GSocket_Init(void)
130{
131 WSADATA wsaData;
132
133 if (!gs_gui_functions)
134 {
135 static GSocketGUIFunctionsTableNull table;
136 gs_gui_functions = &table;
137 }
138 if ( !gs_gui_functions->OnInit() )
139 {
140 return 0;
141 }
142
143 /* Initialize WinSocket */
144 return (WSAStartup((1 << 8) | 1, &wsaData) == 0);
145}
146
147void GSocket_Cleanup(void)
148{
149 if (gs_gui_functions)
150 {
151 gs_gui_functions->OnExit();
152 }
153
154 /* Cleanup WinSocket */
155 WSACleanup();
156}
157
158/* Constructors / Destructors for GSocket */
159
160GSocket::GSocket()
161{
162 int i;
163
164 m_fd = INVALID_SOCKET;
165 for (i = 0; i < GSOCK_MAX_EVENT; i++)
166 {
167 m_cbacks[i] = NULL;
168 }
169 m_detected = 0;
170 m_local = NULL;
171 m_peer = NULL;
172 m_error = GSOCK_NOERROR;
173 m_server = false;
174 m_stream = true;
175 m_non_blocking = false;
176 m_timeout.tv_sec = 10 * 60; /* 10 minutes */
177 m_timeout.tv_usec = 0;
178 m_establishing = false;
179 m_reusable = false;
180 m_broadcast = false;
181 m_dobind = true;
182
183 assert(gs_gui_functions);
184 /* Per-socket GUI-specific initialization */
185 m_ok = gs_gui_functions->Init_Socket(this);
186}
187
188void GSocket::Close()
189{
190 gs_gui_functions->Disable_Events(this);
191 closesocket(m_fd);
192 m_fd = INVALID_SOCKET;
193}
194
195GSocket::~GSocket()
196{
197 assert(this);
198
199 /* Per-socket GUI-specific cleanup */
200 gs_gui_functions->Destroy_Socket(this);
201
202 /* Check that the socket is really shutdowned */
203 if (m_fd != INVALID_SOCKET)
204 Shutdown();
205
206 /* Destroy private addresses */
207 if (m_local)
208 GAddress_destroy(m_local);
209
210 if (m_peer)
211 GAddress_destroy(m_peer);
212}
213
214/* GSocket_Shutdown:
215 * Disallow further read/write operations on this socket, close
216 * the fd and disable all callbacks.
217 */
218void GSocket::Shutdown()
219{
220 int evt;
221
222 assert(this);
223
224 /* If socket has been created, shutdown it */
225 if (m_fd != INVALID_SOCKET)
226 {
227 shutdown(m_fd, 1 /* SD_SEND */);
228 Close();
229 }
230
231 /* Disable GUI callbacks */
232 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
233 m_cbacks[evt] = NULL;
234
235 m_detected = GSOCK_LOST_FLAG;
236}
237
238/* Address handling */
239
240/* GSocket_SetLocal:
241 * GSocket_GetLocal:
242 * GSocket_SetPeer:
243 * GSocket_GetPeer:
244 * Set or get the local or peer address for this socket. The 'set'
245 * functions return GSOCK_NOERROR on success, an error code otherwise.
246 * The 'get' functions return a pointer to a GAddress object on success,
247 * or NULL otherwise, in which case they set the error code of the
248 * corresponding GSocket.
249 *
250 * Error codes:
251 * GSOCK_INVSOCK - the socket is not valid.
252 * GSOCK_INVADDR - the address is not valid.
253 */
254GSocketError GSocket::SetLocal(GAddress *address)
255{
256 assert(this);
257
258 /* the socket must be initialized, or it must be a server */
259 if (m_fd != INVALID_SOCKET && !m_server)
260 {
261 m_error = GSOCK_INVSOCK;
262 return GSOCK_INVSOCK;
263 }
264
265 /* check address */
266 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
267 {
268 m_error = GSOCK_INVADDR;
269 return GSOCK_INVADDR;
270 }
271
272 if (m_local)
273 GAddress_destroy(m_local);
274
275 m_local = GAddress_copy(address);
276
277 return GSOCK_NOERROR;
278}
279
280GSocketError GSocket::SetPeer(GAddress *address)
281{
282 assert(this);
283
284 /* check address */
285 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
286 {
287 m_error = GSOCK_INVADDR;
288 return GSOCK_INVADDR;
289 }
290
291 if (m_peer)
292 GAddress_destroy(m_peer);
293
294 m_peer = GAddress_copy(address);
295
296 return GSOCK_NOERROR;
297}
298
299GAddress *GSocket::GetLocal()
300{
301 GAddress *address;
302 struct sockaddr addr;
303 WX_SOCKLEN_T size = sizeof(addr);
304 GSocketError err;
305
306 assert(this);
307
308 /* try to get it from the m_local var first */
309 if (m_local)
310 return GAddress_copy(m_local);
311
312 /* else, if the socket is initialized, try getsockname */
313 if (m_fd == INVALID_SOCKET)
314 {
315 m_error = GSOCK_INVSOCK;
316 return NULL;
317 }
318
319 if (getsockname(m_fd, &addr, &size) == SOCKET_ERROR)
320 {
321 m_error = GSOCK_IOERR;
322 return NULL;
323 }
324
325 /* got a valid address from getsockname, create a GAddress object */
326 if ((address = GAddress_new()) == NULL)
327 {
328 m_error = GSOCK_MEMERR;
329 return NULL;
330 }
331
332 if ((err = _GAddress_translate_from(address, &addr, size)) != GSOCK_NOERROR)
333 {
334 GAddress_destroy(address);
335 m_error = err;
336 return NULL;
337 }
338
339 return address;
340}
341
342GAddress *GSocket::GetPeer()
343{
344 assert(this);
345
346 /* try to get it from the m_peer var */
347 if (m_peer)
348 return GAddress_copy(m_peer);
349
350 return NULL;
351}
352
353/* Server specific parts */
354
355/* GSocket_SetServer:
356 * Sets up this socket as a server. The local address must have been
357 * set with GSocket_SetLocal() before GSocket_SetServer() is called.
358 * Returns GSOCK_NOERROR on success, one of the following otherwise:
359 *
360 * Error codes:
361 * GSOCK_INVSOCK - the socket is in use.
362 * GSOCK_INVADDR - the local address has not been set.
363 * GSOCK_IOERR - low-level error.
364 */
365GSocketError GSocket::SetServer()
366{
367 u_long arg = 1;
368
369 assert(this);
370
371 /* must not be in use */
372 if (m_fd != INVALID_SOCKET)
373 {
374 m_error = GSOCK_INVSOCK;
375 return GSOCK_INVSOCK;
376 }
377
378 /* the local addr must have been set */
379 if (!m_local)
380 {
381 m_error = GSOCK_INVADDR;
382 return GSOCK_INVADDR;
383 }
384
385 /* Initialize all fields */
386 m_server = true;
387 m_stream = true;
388
389 /* Create the socket */
390 m_fd = socket(m_local->m_realfamily, SOCK_STREAM, 0);
391
392 if (m_fd == INVALID_SOCKET)
393 {
394 m_error = GSOCK_IOERR;
395 return GSOCK_IOERR;
396 }
397
398 ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
399 gs_gui_functions->Enable_Events(this);
400
401 /* allow a socket to re-bind if the socket is in the TIME_WAIT
402 state after being previously closed.
403 */
404 if (m_reusable)
405 {
406 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
407 }
408
409 /* Bind to the local address,
410 * retrieve the actual address bound,
411 * and listen up to 5 connections.
412 */
413 if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
414 (getsockname(m_fd,
415 m_local->m_addr,
416 (WX_SOCKLEN_T *)&m_local->m_len) != 0) ||
417 (listen(m_fd, 5) != 0))
418 {
419 Close();
420 m_error = GSOCK_IOERR;
421 return GSOCK_IOERR;
422 }
423
424 return GSOCK_NOERROR;
425}
426
427/* GSocket_WaitConnection:
428 * Waits for an incoming client connection. Returns a pointer to
429 * a GSocket object, or NULL if there was an error, in which case
430 * the last error field will be updated for the calling GSocket.
431 *
432 * Error codes (set in the calling GSocket)
433 * GSOCK_INVSOCK - the socket is not valid or not a server.
434 * GSOCK_TIMEDOUT - timeout, no incoming connections.
435 * GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking.
436 * GSOCK_MEMERR - couldn't allocate memory.
437 * GSOCK_IOERR - low-level error.
438 */
439GSocket *GSocket::WaitConnection()
440{
441 GSocket *connection;
442 struct sockaddr from;
443 WX_SOCKLEN_T fromlen = sizeof(from);
444 GSocketError err;
445 u_long arg = 1;
446
447 assert(this);
448
449 /* Reenable CONNECTION events */
450 m_detected &= ~GSOCK_CONNECTION_FLAG;
451
452 /* If the socket has already been created, we exit immediately */
453 if (m_fd == INVALID_SOCKET || !m_server)
454 {
455 m_error = GSOCK_INVSOCK;
456 return NULL;
457 }
458
459 /* Create a GSocket object for the new connection */
460 connection = GSocket_new();
461
462 if (!connection)
463 {
464 m_error = GSOCK_MEMERR;
465 return NULL;
466 }
467
468 /* Wait for a connection (with timeout) */
469 if (Input_Timeout() == GSOCK_TIMEDOUT)
470 {
471 delete connection;
472 /* m_error set by _GSocket_Input_Timeout */
473 return NULL;
474 }
475
476 connection->m_fd = accept(m_fd, &from, &fromlen);
477
478 if (connection->m_fd == INVALID_SOCKET)
479 {
480 if (WSAGetLastError() == WSAEWOULDBLOCK)
481 m_error = GSOCK_WOULDBLOCK;
482 else
483 m_error = GSOCK_IOERR;
484
485 delete connection;
486 return NULL;
487 }
488
489 /* Initialize all fields */
490 connection->m_server = false;
491 connection->m_stream = true;
492
493 /* Setup the peer address field */
494 connection->m_peer = GAddress_new();
495 if (!connection->m_peer)
496 {
497 delete connection;
498 m_error = GSOCK_MEMERR;
499 return NULL;
500 }
501 err = _GAddress_translate_from(connection->m_peer, &from, fromlen);
502 if (err != GSOCK_NOERROR)
503 {
504 GAddress_destroy(connection->m_peer);
505 delete connection;
506 m_error = err;
507 return NULL;
508 }
509
510 ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
511 gs_gui_functions->Enable_Events(connection);
512
513 return connection;
514}
515
516/* GSocket_SetReusable:
517* Simply sets the m_resuable flag on the socket. GSocket_SetServer will
518* make the appropriate setsockopt() call.
519* Implemented as a GSocket function because clients (ie, wxSocketServer)
520* don't have access to the GSocket struct information.
521* Returns true if the flag was set correctly, false if an error occurred
522* (ie, if the parameter was NULL)
523*/
524bool GSocket::SetReusable()
525{
526 /* socket must not be null, and must not be in use/already bound */
527 if (this && m_fd == INVALID_SOCKET) {
528 m_reusable = true;
529 return true;
530 }
531 return false;
532}
533
534/* GSocket_SetBroadcast:
535* Simply sets the m_broadcast flag on the socket. GSocket_SetServer will
536* make the appropriate setsockopt() call.
537* Implemented as a GSocket function because clients (ie, wxSocketServer)
538* don't have access to the GSocket struct information.
539* Returns true if the flag was set correctly, false if an error occurred
540* (ie, if the parameter was NULL)
541*/
542bool GSocket::SetBroadcast()
543{
544 /* socket must not be in use/already bound */
545 if (m_fd == INVALID_SOCKET) {
546 m_broadcast = true;
547 return true;
548 }
549 return false;
550}
551
552bool GSocket::DontDoBind()
553{
554 /* socket must not be in use/already bound */
555 if (m_fd == INVALID_SOCKET) {
556 m_dobind = false;
557 return true;
558 }
559 return false;
560}
561
562/* Client specific parts */
563
564/* GSocket_Connect:
565 * For stream (connection oriented) sockets, GSocket_Connect() tries
566 * to establish a client connection to a server using the peer address
567 * as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the
568 * connection has been successfully established, or one of the error
569 * codes listed below. Note that for nonblocking sockets, a return
570 * value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection
571 * request can be completed later; you should use GSocket_Select()
572 * to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the
573 * corresponding asynchronous events.
574 *
575 * For datagram (non connection oriented) sockets, GSocket_Connect()
576 * just sets the peer address established with GSocket_SetPeer() as
577 * default destination.
578 *
579 * Error codes:
580 * GSOCK_INVSOCK - the socket is in use or not valid.
581 * GSOCK_INVADDR - the peer address has not been established.
582 * GSOCK_TIMEDOUT - timeout, the connection failed.
583 * GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only)
584 * GSOCK_MEMERR - couldn't allocate memory.
585 * GSOCK_IOERR - low-level error.
586 */
587GSocketError GSocket::Connect(GSocketStream stream)
588{
589 int ret, err;
590 u_long arg = 1;
591
592 assert(this);
593
594 /* Enable CONNECTION events (needed for nonblocking connections) */
595 m_detected &= ~GSOCK_CONNECTION_FLAG;
596
597 if (m_fd != INVALID_SOCKET)
598 {
599 m_error = GSOCK_INVSOCK;
600 return GSOCK_INVSOCK;
601 }
602
603 if (!m_peer)
604 {
605 m_error = GSOCK_INVADDR;
606 return GSOCK_INVADDR;
607 }
608
609 /* Streamed or dgram socket? */
610 m_stream = (stream == GSOCK_STREAMED);
611 m_server = false;
612 m_establishing = false;
613
614 /* Create the socket */
615 m_fd = socket(m_peer->m_realfamily,
616 m_stream? SOCK_STREAM : SOCK_DGRAM, 0);
617
618 if (m_fd == INVALID_SOCKET)
619 {
620 m_error = GSOCK_IOERR;
621 return GSOCK_IOERR;
622 }
623
624 ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
625 gs_gui_functions->Enable_Events(this);
626
627 // If the reuse flag is set, use the applicable socket reuse flag
628 if (m_reusable)
629 {
630 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
631 }
632
633 // If a local address has been set, then we need to bind to it before calling connect
634 if (m_local && m_local->m_addr)
635 {
636 bind(m_fd, m_local->m_addr, m_local->m_len);
637 }
638
639 /* Connect it to the peer address, with a timeout (see below) */
640 ret = connect(m_fd, m_peer->m_addr, m_peer->m_len);
641
642 if (ret == SOCKET_ERROR)
643 {
644 err = WSAGetLastError();
645
646 /* If connect failed with EWOULDBLOCK and the GSocket object
647 * is in blocking mode, we select() for the specified timeout
648 * checking for writability to see if the connection request
649 * completes.
650 */
651 if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
652 {
653 err = Connect_Timeout();
654
655 if (err != GSOCK_NOERROR)
656 {
657 Close();
658 /* m_error is set in _GSocket_Connect_Timeout */
659 }
660
661 return (GSocketError) err;
662 }
663
664 /* If connect failed with EWOULDBLOCK and the GSocket object
665 * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK
666 * (and return GSOCK_WOULDBLOCK) but we don't close the socket;
667 * this way if the connection completes, a GSOCK_CONNECTION
668 * event will be generated, if enabled.
669 */
670 if ((err == WSAEWOULDBLOCK) && (m_non_blocking))
671 {
672 m_establishing = true;
673 m_error = GSOCK_WOULDBLOCK;
674 return GSOCK_WOULDBLOCK;
675 }
676
677 /* If connect failed with an error other than EWOULDBLOCK,
678 * then the call to GSocket_Connect() has failed.
679 */
680 Close();
681 m_error = GSOCK_IOERR;
682 return GSOCK_IOERR;
683 }
684
685 return GSOCK_NOERROR;
686}
687
688/* Datagram sockets */
689
690/* GSocket_SetNonOriented:
691 * Sets up this socket as a non-connection oriented (datagram) socket.
692 * Before using this function, the local address must have been set
693 * with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR
694 * on success, or one of the following otherwise.
695 *
696 * Error codes:
697 * GSOCK_INVSOCK - the socket is in use.
698 * GSOCK_INVADDR - the local address has not been set.
699 * GSOCK_IOERR - low-level error.
700 */
701GSocketError GSocket::SetNonOriented()
702{
703 u_long arg = 1;
704
705 assert(this);
706
707 if (m_fd != INVALID_SOCKET)
708 {
709 m_error = GSOCK_INVSOCK;
710 return GSOCK_INVSOCK;
711 }
712
713 if (!m_local)
714 {
715 m_error = GSOCK_INVADDR;
716 return GSOCK_INVADDR;
717 }
718
719 /* Initialize all fields */
720 m_stream = false;
721 m_server = false;
722
723 /* Create the socket */
724 m_fd = socket(m_local->m_realfamily, SOCK_DGRAM, 0);
725
726 if (m_fd == INVALID_SOCKET)
727 {
728 m_error = GSOCK_IOERR;
729 return GSOCK_IOERR;
730 }
731
732 ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
733 gs_gui_functions->Enable_Events(this);
734
735 if (m_reusable)
736 {
737 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
738 }
739 if (m_broadcast)
740 {
741 setsockopt(m_fd, SOL_SOCKET, SO_BROADCAST, (const char*)&arg, sizeof(arg));
742 }
743 if (m_dobind)
744 {
745 /* Bind to the local address,
746 * and retrieve the actual address bound.
747 */
748 if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
749 (getsockname(m_fd,
750 m_local->m_addr,
751 (WX_SOCKLEN_T *)&m_local->m_len) != 0))
752 {
753 Close();
754 m_error = GSOCK_IOERR;
755 return GSOCK_IOERR;
756 }
757 }
758
759 return GSOCK_NOERROR;
760}
761
762/* Generic IO */
763
764/* Like recv(), send(), ... */
765int GSocket::Read(char *buffer, int size)
766{
767 int ret;
768
769 assert(this);
770
771 /* Reenable INPUT events */
772 m_detected &= ~GSOCK_INPUT_FLAG;
773
774 if (m_fd == INVALID_SOCKET || m_server)
775 {
776 m_error = GSOCK_INVSOCK;
777 return -1;
778 }
779
780 /* If the socket is blocking, wait for data (with a timeout) */
781 if (Input_Timeout() == GSOCK_TIMEDOUT)
782 {
783 m_error = GSOCK_TIMEDOUT;
784 return -1;
785 }
786
787 /* Read the data */
788 if (m_stream)
789 ret = Recv_Stream(buffer, size);
790 else
791 ret = Recv_Dgram(buffer, size);
792
793 if (ret == SOCKET_ERROR)
794 {
795 if (WSAGetLastError() != WSAEWOULDBLOCK)
796 m_error = GSOCK_IOERR;
797 else
798 m_error = GSOCK_WOULDBLOCK;
799 return -1;
800 }
801
802 return ret;
803}
804
805int GSocket::Write(const char *buffer, int size)
806{
807 int ret;
808
809 assert(this);
810
811 if (m_fd == INVALID_SOCKET || m_server)
812 {
813 m_error = GSOCK_INVSOCK;
814 return -1;
815 }
816
817 /* If the socket is blocking, wait for writability (with a timeout) */
818 if (Output_Timeout() == GSOCK_TIMEDOUT)
819 return -1;
820
821 /* Write the data */
822 if (m_stream)
823 ret = Send_Stream(buffer, size);
824 else
825 ret = Send_Dgram(buffer, size);
826
827 if (ret == SOCKET_ERROR)
828 {
829 if (WSAGetLastError() != WSAEWOULDBLOCK)
830 m_error = GSOCK_IOERR;
831 else
832 m_error = GSOCK_WOULDBLOCK;
833
834 /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
835 * does). Once the first OUTPUT event is received, users can assume
836 * that the socket is writable until a read operation fails. Only then
837 * will further OUTPUT events be posted.
838 */
839 m_detected &= ~GSOCK_OUTPUT_FLAG;
840 return -1;
841 }
842
843 return ret;
844}
845
846/* GSocket_Select:
847 * Polls the socket to determine its status. This function will
848 * check for the events specified in the 'flags' parameter, and
849 * it will return a mask indicating which operations can be
850 * performed. This function won't block, regardless of the
851 * mode (blocking | nonblocking) of the socket.
852 */
853GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
854{
855 if (!gs_gui_functions->CanUseEventLoop())
856 {
857 GSocketEventFlags result = 0;
858 fd_set readfds;
859 fd_set writefds;
860 fd_set exceptfds;
861
862 assert(this);
863
864 FD_ZERO(&readfds);
865 FD_ZERO(&writefds);
866 FD_ZERO(&exceptfds);
867 FD_SET(m_fd, &readfds);
868 if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
869 FD_SET(m_fd, &writefds);
870 FD_SET(m_fd, &exceptfds);
871
872 /* Check 'sticky' CONNECTION flag first */
873 result |= (GSOCK_CONNECTION_FLAG & m_detected);
874
875 /* If we have already detected a LOST event, then don't try
876 * to do any further processing.
877 */
878 if ((m_detected & GSOCK_LOST_FLAG) != 0)
879 {
880 m_establishing = false;
881
882 return (GSOCK_LOST_FLAG & flags);
883 }
884
885 /* Try select now */
886 if (select(m_fd + 1, &readfds, &writefds, &exceptfds,
887 &m_timeout) <= 0)
888 {
889 /* What to do here? */
890 return (result & flags);
891 }
892
893 /* Check for exceptions and errors */
894 if (FD_ISSET(m_fd, &exceptfds))
895 {
896 m_establishing = false;
897 m_detected = GSOCK_LOST_FLAG;
898
899 /* LOST event: Abort any further processing */
900 return (GSOCK_LOST_FLAG & flags);
901 }
902
903 /* Check for readability */
904 if (FD_ISSET(m_fd, &readfds))
905 {
906 result |= GSOCK_INPUT_FLAG;
907
908 if (m_server && m_stream)
909 {
910 /* This is a TCP server socket that detected a connection.
911 While the INPUT_FLAG is also set, it doesn't matter on
912 this kind of sockets, as we can only Accept() from them. */
913 result |= GSOCK_CONNECTION_FLAG;
914 m_detected |= GSOCK_CONNECTION_FLAG;
915 }
916 }
917
918 /* Check for writability */
919 if (FD_ISSET(m_fd, &writefds))
920 {
921 if (m_establishing && !m_server)
922 {
923 int error;
924 WX_SOCKLEN_T len = sizeof(error);
925
926 m_establishing = false;
927
928 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
929
930 if (error)
931 {
932 m_detected = GSOCK_LOST_FLAG;
933
934 /* LOST event: Abort any further processing */
935 return (GSOCK_LOST_FLAG & flags);
936 }
937 else
938 {
939 result |= GSOCK_CONNECTION_FLAG;
940 m_detected |= GSOCK_CONNECTION_FLAG;
941 }
942 }
943 else
944 {
945 result |= GSOCK_OUTPUT_FLAG;
946 }
947 }
948
949 return (result & flags);
950 }
951 else /* USE_GUI() */
952 {
953 assert(this);
954 return flags & m_detected;
955 }
956}
957
958/* Attributes */
959
960/* GSocket_SetNonBlocking:
961 * Sets the socket to non-blocking mode. All IO calls will return
962 * immediately.
963 */
964void GSocket::SetNonBlocking(bool non_block)
965{
966 assert(this);
967
968 m_non_blocking = non_block;
969}
970
971/* GSocket_SetTimeout:
972 * Sets the timeout for blocking calls. Time is expressed in
973 * milliseconds.
974 */
975void GSocket::SetTimeout(unsigned long millis)
976{
977 assert(this);
978
979 m_timeout.tv_sec = (millis / 1000);
980 m_timeout.tv_usec = (millis % 1000) * 1000;
981}
982
983/* GSocket_GetError:
984 * Returns the last error occurred for this socket. Note that successful
985 * operations do not clear this back to GSOCK_NOERROR, so use it only
986 * after an error.
987 */
988GSocketError WXDLLIMPEXP_NET GSocket::GetError()
989{
990 assert(this);
991
992 return m_error;
993}
994
995/* Callbacks */
996
997/* GSOCK_INPUT:
998 * There is data to be read in the input buffer. If, after a read
999 * operation, there is still data available, the callback function will
1000 * be called again.
1001 * GSOCK_OUTPUT:
1002 * The socket is available for writing. That is, the next write call
1003 * won't block. This event is generated only once, when the connection is
1004 * first established, and then only if a call failed with GSOCK_WOULDBLOCK,
1005 * when the output buffer empties again. This means that the app should
1006 * assume that it can write since the first OUTPUT event, and no more
1007 * OUTPUT events will be generated unless an error occurs.
1008 * GSOCK_CONNECTION:
1009 * Connection successfully established, for client sockets, or incoming
1010 * client connection, for server sockets. Wait for this event (also watch
1011 * out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call.
1012 * GSOCK_LOST:
1013 * The connection is lost (or a connection request failed); this could
1014 * be due to a failure, or due to the peer closing it gracefully.
1015 */
1016
1017/* GSocket_SetCallback:
1018 * Enables the callbacks specified by 'flags'. Note that 'flags'
1019 * may be a combination of flags OR'ed toghether, so the same
1020 * callback function can be made to accept different events.
1021 * The callback function must have the following prototype:
1022 *
1023 * void function(GSocket *socket, GSocketEvent event, char *cdata)
1024 */
1025void GSocket::SetCallback(GSocketEventFlags flags,
1026 GSocketCallback callback, char *cdata)
1027{
1028 int count;
1029
1030 assert(this);
1031
1032 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1033 {
1034 if ((flags & (1 << count)) != 0)
1035 {
1036 m_cbacks[count] = callback;
1037 m_data[count] = cdata;
1038 }
1039 }
1040}
1041
1042/* GSocket_UnsetCallback:
1043 * Disables all callbacks specified by 'flags', which may be a
1044 * combination of flags OR'ed toghether.
1045 */
1046void GSocket::UnsetCallback(GSocketEventFlags flags)
1047{
1048 int count;
1049
1050 assert(this);
1051
1052 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1053 {
1054 if ((flags & (1 << count)) != 0)
1055 {
1056 m_cbacks[count] = NULL;
1057 m_data[count] = NULL;
1058 }
1059 }
1060}
1061
1062GSocketError GSocket::GetSockOpt(int level, int optname,
1063 void *optval, int *optlen)
1064{
1065 if (getsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
1066 {
1067 return GSOCK_NOERROR;
1068 }
1069 return GSOCK_OPTERR;
1070}
1071
1072GSocketError GSocket::SetSockOpt(int level, int optname,
1073 const void *optval, int optlen)
1074{
1075 if (setsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
1076 {
1077 return GSOCK_NOERROR;
1078 }
1079 return GSOCK_OPTERR;
1080}
1081
1082/* Internals (IO) */
1083
1084/* _GSocket_Input_Timeout:
1085 * For blocking sockets, wait until data is available or
1086 * until timeout ellapses.
1087 */
1088GSocketError GSocket::Input_Timeout()
1089{
1090 fd_set readfds;
1091
1092 if (!m_non_blocking)
1093 {
1094 FD_ZERO(&readfds);
1095 FD_SET(m_fd, &readfds);
1096 if (select(0, &readfds, NULL, NULL, &m_timeout) == 0)
1097 {
1098 m_error = GSOCK_TIMEDOUT;
1099 return GSOCK_TIMEDOUT;
1100 }
1101 }
1102 return GSOCK_NOERROR;
1103}
1104
1105/* _GSocket_Output_Timeout:
1106 * For blocking sockets, wait until data can be sent without
1107 * blocking or until timeout ellapses.
1108 */
1109GSocketError GSocket::Output_Timeout()
1110{
1111 fd_set writefds;
1112
1113 if (!m_non_blocking)
1114 {
1115 FD_ZERO(&writefds);
1116 FD_SET(m_fd, &writefds);
1117 if (select(0, NULL, &writefds, NULL, &m_timeout) == 0)
1118 {
1119 m_error = GSOCK_TIMEDOUT;
1120 return GSOCK_TIMEDOUT;
1121 }
1122 }
1123 return GSOCK_NOERROR;
1124}
1125
1126/* _GSocket_Connect_Timeout:
1127 * For blocking sockets, wait until the connection is
1128 * established or fails, or until timeout ellapses.
1129 */
1130GSocketError GSocket::Connect_Timeout()
1131{
1132 fd_set writefds;
1133 fd_set exceptfds;
1134
1135 FD_ZERO(&writefds);
1136 FD_ZERO(&exceptfds);
1137 FD_SET(m_fd, &writefds);
1138 FD_SET(m_fd, &exceptfds);
1139 if (select(0, NULL, &writefds, &exceptfds, &m_timeout) == 0)
1140 {
1141 m_error = GSOCK_TIMEDOUT;
1142 return GSOCK_TIMEDOUT;
1143 }
1144 if (!FD_ISSET(m_fd, &writefds))
1145 {
1146 m_error = GSOCK_IOERR;
1147 return GSOCK_IOERR;
1148 }
1149
1150 return GSOCK_NOERROR;
1151}
1152
1153int GSocket::Recv_Stream(char *buffer, int size)
1154{
1155 return recv(m_fd, buffer, size, 0);
1156}
1157
1158int GSocket::Recv_Dgram(char *buffer, int size)
1159{
1160 struct sockaddr from;
1161 WX_SOCKLEN_T fromlen = sizeof(from);
1162 int ret;
1163 GSocketError err;
1164
1165 ret = recvfrom(m_fd, buffer, size, 0, &from, &fromlen);
1166
1167 if (ret == SOCKET_ERROR)
1168 return SOCKET_ERROR;
1169
1170 /* Translate a system address into a GSocket address */
1171 if (!m_peer)
1172 {
1173 m_peer = GAddress_new();
1174 if (!m_peer)
1175 {
1176 m_error = GSOCK_MEMERR;
1177 return -1;
1178 }
1179 }
1180 err = _GAddress_translate_from(m_peer, &from, fromlen);
1181 if (err != GSOCK_NOERROR)
1182 {
1183 GAddress_destroy(m_peer);
1184 m_peer = NULL;
1185 m_error = err;
1186 return -1;
1187 }
1188
1189 return ret;
1190}
1191
1192int GSocket::Send_Stream(const char *buffer, int size)
1193{
1194 return send(m_fd, buffer, size, 0);
1195}
1196
1197int GSocket::Send_Dgram(const char *buffer, int size)
1198{
1199 struct sockaddr *addr;
1200 int len, ret;
1201 GSocketError err;
1202
1203 if (!m_peer)
1204 {
1205 m_error = GSOCK_INVADDR;
1206 return -1;
1207 }
1208
1209 err = _GAddress_translate_to(m_peer, &addr, &len);
1210 if (err != GSOCK_NOERROR)
1211 {
1212 m_error = err;
1213 return -1;
1214 }
1215
1216 ret = sendto(m_fd, buffer, size, 0, addr, len);
1217
1218 /* Frees memory allocated by _GAddress_translate_to */
1219 free(addr);
1220
1221 return ret;
1222}
1223
1224/* Compatibility functions for GSocket */
1225GSocket *GSocket_new(void)
1226{
1227 GSocket *newsocket = new GSocket();
1228 if(newsocket->IsOk())
1229 return newsocket;
1230 delete newsocket;
1231 return NULL;
1232}
1233
1234
1235/*
1236 * -------------------------------------------------------------------------
1237 * GAddress
1238 * -------------------------------------------------------------------------
1239 */
1240
1241/* CHECK_ADDRESS verifies that the current address family is either
1242 * GSOCK_NOFAMILY or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it
1243 * initalizes it to be a GSOCK_*family*. In other cases, it returns
1244 * an appropiate error code.
1245 *
1246 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
1247 */
1248#define CHECK_ADDRESS(address, family) \
1249{ \
1250 if (address->m_family == GSOCK_NOFAMILY) \
1251 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1252 return address->m_error; \
1253 if (address->m_family != GSOCK_##family) \
1254 { \
1255 address->m_error = GSOCK_INVADDR; \
1256 return GSOCK_INVADDR; \
1257 } \
1258}
1259
1260#define CHECK_ADDRESS_RETVAL(address, family, retval) \
1261{ \
1262 if (address->m_family == GSOCK_NOFAMILY) \
1263 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1264 return retval; \
1265 if (address->m_family != GSOCK_##family) \
1266 { \
1267 address->m_error = GSOCK_INVADDR; \
1268 return retval; \
1269 } \
1270}
1271
1272
1273GAddress *GAddress_new(void)
1274{
1275 GAddress *address;
1276
1277 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1278 return NULL;
1279
1280 address->m_family = GSOCK_NOFAMILY;
1281 address->m_addr = NULL;
1282 address->m_len = 0;
1283
1284 return address;
1285}
1286
1287GAddress *GAddress_copy(GAddress *address)
1288{
1289 GAddress *addr2;
1290
1291 assert(address != NULL);
1292
1293 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1294 return NULL;
1295
1296 memcpy(addr2, address, sizeof(GAddress));
1297
1298 if (address->m_addr)
1299 {
1300 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
1301 if (addr2->m_addr == NULL)
1302 {
1303 free(addr2);
1304 return NULL;
1305 }
1306 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1307 }
1308
1309 return addr2;
1310}
1311
1312void GAddress_destroy(GAddress *address)
1313{
1314 assert(address != NULL);
1315
1316 if (address->m_addr)
1317 free(address->m_addr);
1318
1319 free(address);
1320}
1321
1322void GAddress_SetFamily(GAddress *address, GAddressType type)
1323{
1324 assert(address != NULL);
1325
1326 address->m_family = type;
1327}
1328
1329GAddressType GAddress_GetFamily(GAddress *address)
1330{
1331 assert(address != NULL);
1332
1333 return address->m_family;
1334}
1335
1336GSocketError _GAddress_translate_from(GAddress *address,
1337 struct sockaddr *addr, int len)
1338{
1339 address->m_realfamily = addr->sa_family;
1340 switch (addr->sa_family)
1341 {
1342 case AF_INET:
1343 address->m_family = GSOCK_INET;
1344 break;
1345 case AF_UNIX:
1346 address->m_family = GSOCK_UNIX;
1347 break;
1348#ifdef AF_INET6
1349 case AF_INET6:
1350 address->m_family = GSOCK_INET6;
1351 break;
1352#endif
1353 default:
1354 {
1355 address->m_error = GSOCK_INVOP;
1356 return GSOCK_INVOP;
1357 }
1358 }
1359
1360 if (address->m_addr)
1361 free(address->m_addr);
1362
1363 address->m_len = len;
1364 address->m_addr = (struct sockaddr *) malloc(len);
1365
1366 if (address->m_addr == NULL)
1367 {
1368 address->m_error = GSOCK_MEMERR;
1369 return GSOCK_MEMERR;
1370 }
1371 memcpy(address->m_addr, addr, len);
1372
1373 return GSOCK_NOERROR;
1374}
1375
1376GSocketError _GAddress_translate_to(GAddress *address,
1377 struct sockaddr **addr, int *len)
1378{
1379 if (!address->m_addr)
1380 {
1381 address->m_error = GSOCK_INVADDR;
1382 return GSOCK_INVADDR;
1383 }
1384
1385 *len = address->m_len;
1386 *addr = (struct sockaddr *) malloc(address->m_len);
1387 if (*addr == NULL)
1388 {
1389 address->m_error = GSOCK_MEMERR;
1390 return GSOCK_MEMERR;
1391 }
1392
1393 memcpy(*addr, address->m_addr, address->m_len);
1394 return GSOCK_NOERROR;
1395}
1396
1397/*
1398 * -------------------------------------------------------------------------
1399 * Internet address family
1400 * -------------------------------------------------------------------------
1401 */
1402
1403GSocketError _GAddress_Init_INET(GAddress *address)
1404{
1405 address->m_len = sizeof(struct sockaddr_in);
1406 address->m_addr = (struct sockaddr *) malloc(address->m_len);
1407 if (address->m_addr == NULL)
1408 {
1409 address->m_error = GSOCK_MEMERR;
1410 return GSOCK_MEMERR;
1411 }
1412
1413 address->m_family = GSOCK_INET;
1414 address->m_realfamily = AF_INET;
1415 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
1416 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
1417
1418 return GSOCK_NOERROR;
1419}
1420
1421GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1422{
1423 struct hostent *he;
1424 struct in_addr *addr;
1425
1426 assert(address != NULL);
1427
1428 CHECK_ADDRESS(address, INET);
1429
1430 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1431
1432 addr->s_addr = inet_addr(hostname);
1433
1434 /* If it is a numeric host name, convert it now */
1435 if (addr->s_addr == INADDR_NONE)
1436 {
1437 struct in_addr *array_addr;
1438
1439 /* It is a real name, we solve it */
1440 if ((he = gethostbyname(hostname)) == NULL)
1441 {
1442 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
1443 address->m_error = GSOCK_NOHOST;
1444 return GSOCK_NOHOST;
1445 }
1446 array_addr = (struct in_addr *) *(he->h_addr_list);
1447 addr->s_addr = array_addr[0].s_addr;
1448 }
1449 return GSOCK_NOERROR;
1450}
1451
1452GSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
1453{
1454 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
1455}
1456
1457GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1458{
1459 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1460}
1461
1462GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1463 unsigned long hostaddr)
1464{
1465 struct in_addr *addr;
1466
1467 assert(address != NULL);
1468
1469 CHECK_ADDRESS(address, INET);
1470
1471 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1472 addr->s_addr = htonl(hostaddr);
1473
1474 return GSOCK_NOERROR;
1475}
1476
1477GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1478 const char *protocol)
1479{
1480 struct servent *se;
1481 struct sockaddr_in *addr;
1482
1483 assert(address != NULL);
1484 CHECK_ADDRESS(address, INET);
1485
1486 if (!port)
1487 {
1488 address->m_error = GSOCK_INVPORT;
1489 return GSOCK_INVPORT;
1490 }
1491
1492 se = getservbyname(port, protocol);
1493 if (!se)
1494 {
1495 if (isdigit(port[0]))
1496 {
1497 int port_int;
1498
1499 port_int = atoi(port);
1500 addr = (struct sockaddr_in *)address->m_addr;
1501 addr->sin_port = htons((u_short) port_int);
1502 return GSOCK_NOERROR;
1503 }
1504
1505 address->m_error = GSOCK_INVPORT;
1506 return GSOCK_INVPORT;
1507 }
1508
1509 addr = (struct sockaddr_in *)address->m_addr;
1510 addr->sin_port = se->s_port;
1511
1512 return GSOCK_NOERROR;
1513}
1514
1515GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1516{
1517 struct sockaddr_in *addr;
1518
1519 assert(address != NULL);
1520 CHECK_ADDRESS(address, INET);
1521
1522 addr = (struct sockaddr_in *)address->m_addr;
1523 addr->sin_port = htons(port);
1524
1525 return GSOCK_NOERROR;
1526}
1527
1528GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1529{
1530 struct hostent *he;
1531 char *addr_buf;
1532 struct sockaddr_in *addr;
1533
1534 assert(address != NULL);
1535 CHECK_ADDRESS(address, INET);
1536
1537 addr = (struct sockaddr_in *)address->m_addr;
1538 addr_buf = (char *)&(addr->sin_addr);
1539
1540 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1541 if (he == NULL)
1542 {
1543 address->m_error = GSOCK_NOHOST;
1544 return GSOCK_NOHOST;
1545 }
1546
1547 strncpy(hostname, he->h_name, sbuf);
1548
1549 return GSOCK_NOERROR;
1550}
1551
1552unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1553{
1554 struct sockaddr_in *addr;
1555
1556 assert(address != NULL);
1557 CHECK_ADDRESS_RETVAL(address, INET, 0);
1558
1559 addr = (struct sockaddr_in *)address->m_addr;
1560
1561 return ntohl(addr->sin_addr.s_addr);
1562}
1563
1564unsigned short GAddress_INET_GetPort(GAddress *address)
1565{
1566 struct sockaddr_in *addr;
1567
1568 assert(address != NULL);
1569 CHECK_ADDRESS_RETVAL(address, INET, 0);
1570
1571 addr = (struct sockaddr_in *)address->m_addr;
1572 return ntohs(addr->sin_port);
1573}
1574
1575/*
1576 * -------------------------------------------------------------------------
1577 * Unix address family
1578 * -------------------------------------------------------------------------
1579 */
1580
1581GSocketError _GAddress_Init_UNIX(GAddress *address)
1582{
1583 assert (address != NULL);
1584 address->m_error = GSOCK_INVADDR;
1585 return GSOCK_INVADDR;
1586}
1587
1588GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
1589{
1590 assert (address != NULL);
1591 address->m_error = GSOCK_INVADDR;
1592 return GSOCK_INVADDR;
1593}
1594
1595GSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
1596{
1597 assert (address != NULL);
1598 address->m_error = GSOCK_INVADDR;
1599 return GSOCK_INVADDR;
1600}
1601
1602#else /* !wxUSE_SOCKETS */
1603
1604/*
1605 * Translation unit shouldn't be empty, so include this typedef to make the
1606 * compiler (VC++ 6.0, for example) happy
1607 */
1608typedef void (*wxDummy)();
1609
1610#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */