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