]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gsocket.cpp
Fixed wxAtomicInc/Dec() to not use asm/atomic.h header on Linux - it's kernel interna...
[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
91/* Table of GUI-related functions. We must call them indirectly because
92 * of wxBase and GUI separation: */
93
3e1400ac 94static GSocketGUIFunctionsTable *gs_gui_functions;
f7ff39c6 95
a4506848
DE
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; }
d95de154 114bool GSocketGUIFunctionsTableNull::Init_Socket(GSocket *WXUNUSED(socket))
a4506848 115{ return true; }
d95de154 116void GSocketGUIFunctionsTableNull::Destroy_Socket(GSocket *WXUNUSED(socket))
a4506848 117{}
d95de154 118void GSocketGUIFunctionsTableNull::Enable_Events(GSocket *WXUNUSED(socket))
a4506848 119{}
d95de154 120void GSocketGUIFunctionsTableNull::Disable_Events(GSocket *WXUNUSED(socket))
a4506848 121{}
f7ff39c6
DE
122/* Global initialisers */
123
3e1400ac 124void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable *guifunc)
f7ff39c6
DE
125{
126 gs_gui_functions = guifunc;
127}
128
129int GSocket_Init(void)
130{
131 WSADATA wsaData;
132
a4506848 133 if (!gs_gui_functions)
f7ff39c6 134 {
3e1400ac 135 static GSocketGUIFunctionsTableNull table;
a4506848
DE
136 gs_gui_functions = &table;
137 }
138 if ( !gs_gui_functions->OnInit() )
139 {
140 return 0;
f7ff39c6
DE
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 {
c90cc42e 151 gs_gui_functions->OnExit();
f7ff39c6
DE
152 }
153
154 /* Cleanup WinSocket */
155 WSACleanup();
156}
157
158/* Constructors / Destructors for GSocket */
159
c90cc42e 160GSocket::GSocket()
f7ff39c6 161{
c90cc42e 162 int i;
f7ff39c6 163
c90cc42e 164 m_fd = INVALID_SOCKET;
f7ff39c6
DE
165 for (i = 0; i < GSOCK_MAX_EVENT; i++)
166 {
c90cc42e 167 m_cbacks[i] = NULL;
f7ff39c6 168 }
c90cc42e
DE
169 m_detected = 0;
170 m_local = NULL;
171 m_peer = NULL;
172 m_error = GSOCK_NOERROR;
948c96ef
DE
173 m_server = false;
174 m_stream = true;
c90cc42e
DE
175 m_non_blocking = false;
176 m_timeout.tv_sec = 10 * 60; /* 10 minutes */
177 m_timeout.tv_usec = 0;
948c96ef
DE
178 m_establishing = false;
179 m_reusable = false;
60edcf45
VZ
180 m_broadcast = false;
181 m_dobind = true;
c90cc42e
DE
182
183 assert(gs_gui_functions);
f7ff39c6 184 /* Per-socket GUI-specific initialization */
c90cc42e 185 m_ok = gs_gui_functions->Init_Socket(this);
f7ff39c6
DE
186}
187
c90cc42e 188void GSocket::Close()
f7ff39c6 189{
c90cc42e
DE
190 gs_gui_functions->Disable_Events(this);
191 closesocket(m_fd);
192 m_fd = INVALID_SOCKET;
f7ff39c6
DE
193}
194
c90cc42e 195GSocket::~GSocket()
f7ff39c6 196{
c90cc42e 197 assert(this);
f7ff39c6
DE
198
199 /* Per-socket GUI-specific cleanup */
c90cc42e 200 gs_gui_functions->Destroy_Socket(this);
f7ff39c6
DE
201
202 /* Check that the socket is really shutdowned */
c90cc42e
DE
203 if (m_fd != INVALID_SOCKET)
204 Shutdown();
f7ff39c6
DE
205
206 /* Destroy private addresses */
c90cc42e
DE
207 if (m_local)
208 GAddress_destroy(m_local);
f7ff39c6 209
c90cc42e
DE
210 if (m_peer)
211 GAddress_destroy(m_peer);
f7ff39c6
DE
212}
213
214/* GSocket_Shutdown:
215 * Disallow further read/write operations on this socket, close
216 * the fd and disable all callbacks.
217 */
c90cc42e 218void GSocket::Shutdown()
f7ff39c6
DE
219{
220 int evt;
221
c90cc42e 222 assert(this);
f7ff39c6
DE
223
224 /* If socket has been created, shutdown it */
c90cc42e 225 if (m_fd != INVALID_SOCKET)
f7ff39c6 226 {
cd632a86 227 shutdown(m_fd, 1 /* SD_SEND */);
c90cc42e 228 Close();
f7ff39c6
DE
229 }
230
231 /* Disable GUI callbacks */
232 for (evt = 0; evt < GSOCK_MAX_EVENT; evt++)
c90cc42e 233 m_cbacks[evt] = NULL;
f7ff39c6 234
c90cc42e 235 m_detected = GSOCK_LOST_FLAG;
f7ff39c6
DE
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 */
c90cc42e 254GSocketError GSocket::SetLocal(GAddress *address)
f7ff39c6 255{
c90cc42e 256 assert(this);
f7ff39c6
DE
257
258 /* the socket must be initialized, or it must be a server */
c90cc42e 259 if (m_fd != INVALID_SOCKET && !m_server)
f7ff39c6 260 {
c90cc42e 261 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
262 return GSOCK_INVSOCK;
263 }
264
265 /* check address */
266 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
267 {
c90cc42e 268 m_error = GSOCK_INVADDR;
f7ff39c6
DE
269 return GSOCK_INVADDR;
270 }
271
c90cc42e
DE
272 if (m_local)
273 GAddress_destroy(m_local);
f7ff39c6 274
c90cc42e 275 m_local = GAddress_copy(address);
f7ff39c6
DE
276
277 return GSOCK_NOERROR;
278}
279
c90cc42e 280GSocketError GSocket::SetPeer(GAddress *address)
f7ff39c6 281{
c90cc42e 282 assert(this);
f7ff39c6
DE
283
284 /* check address */
285 if (address == NULL || address->m_family == GSOCK_NOFAMILY)
286 {
c90cc42e 287 m_error = GSOCK_INVADDR;
f7ff39c6
DE
288 return GSOCK_INVADDR;
289 }
290
c90cc42e
DE
291 if (m_peer)
292 GAddress_destroy(m_peer);
f7ff39c6 293
c90cc42e 294 m_peer = GAddress_copy(address);
f7ff39c6
DE
295
296 return GSOCK_NOERROR;
297}
298
c90cc42e 299GAddress *GSocket::GetLocal()
f7ff39c6
DE
300{
301 GAddress *address;
302 struct sockaddr addr;
9e03e02d 303 WX_SOCKLEN_T size = sizeof(addr);
f7ff39c6
DE
304 GSocketError err;
305
c90cc42e 306 assert(this);
f7ff39c6
DE
307
308 /* try to get it from the m_local var first */
c90cc42e
DE
309 if (m_local)
310 return GAddress_copy(m_local);
f7ff39c6
DE
311
312 /* else, if the socket is initialized, try getsockname */
c90cc42e 313 if (m_fd == INVALID_SOCKET)
f7ff39c6 314 {
c90cc42e 315 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
316 return NULL;
317 }
318
c90cc42e 319 if (getsockname(m_fd, &addr, &size) == SOCKET_ERROR)
f7ff39c6 320 {
c90cc42e 321 m_error = GSOCK_IOERR;
f7ff39c6
DE
322 return NULL;
323 }
324
325 /* got a valid address from getsockname, create a GAddress object */
326 if ((address = GAddress_new()) == NULL)
327 {
c90cc42e 328 m_error = GSOCK_MEMERR;
f7ff39c6
DE
329 return NULL;
330 }
331
332 if ((err = _GAddress_translate_from(address, &addr, size)) != GSOCK_NOERROR)
333 {
334 GAddress_destroy(address);
c90cc42e 335 m_error = err;
f7ff39c6
DE
336 return NULL;
337 }
338
339 return address;
340}
341
c90cc42e 342GAddress *GSocket::GetPeer()
f7ff39c6 343{
c90cc42e 344 assert(this);
f7ff39c6
DE
345
346 /* try to get it from the m_peer var */
c90cc42e
DE
347 if (m_peer)
348 return GAddress_copy(m_peer);
f7ff39c6
DE
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 */
c90cc42e 365GSocketError GSocket::SetServer()
f7ff39c6
DE
366{
367 u_long arg = 1;
368
c90cc42e 369 assert(this);
f7ff39c6
DE
370
371 /* must not be in use */
c90cc42e 372 if (m_fd != INVALID_SOCKET)
f7ff39c6 373 {
c90cc42e 374 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
375 return GSOCK_INVSOCK;
376 }
377
378 /* the local addr must have been set */
c90cc42e 379 if (!m_local)
f7ff39c6 380 {
c90cc42e 381 m_error = GSOCK_INVADDR;
f7ff39c6
DE
382 return GSOCK_INVADDR;
383 }
384
385 /* Initialize all fields */
948c96ef
DE
386 m_server = true;
387 m_stream = true;
f7ff39c6
DE
388
389 /* Create the socket */
c90cc42e 390 m_fd = socket(m_local->m_realfamily, SOCK_STREAM, 0);
f7ff39c6 391
c90cc42e 392 if (m_fd == INVALID_SOCKET)
f7ff39c6 393 {
c90cc42e 394 m_error = GSOCK_IOERR;
f7ff39c6
DE
395 return GSOCK_IOERR;
396 }
397
c90cc42e
DE
398 ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
399 gs_gui_functions->Enable_Events(this);
f7ff39c6
DE
400
401 /* allow a socket to re-bind if the socket is in the TIME_WAIT
402 state after being previously closed.
403 */
28bf2f3c
VZ
404 if (m_reusable)
405 {
406 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
f7ff39c6
DE
407 }
408
409 /* Bind to the local address,
410 * retrieve the actual address bound,
411 * and listen up to 5 connections.
412 */
c90cc42e
DE
413 if ((bind(m_fd, m_local->m_addr, m_local->m_len) != 0) ||
414 (getsockname(m_fd,
415 m_local->m_addr,
9e03e02d 416 (WX_SOCKLEN_T *)&m_local->m_len) != 0) ||
c90cc42e 417 (listen(m_fd, 5) != 0))
f7ff39c6 418 {
c90cc42e
DE
419 Close();
420 m_error = GSOCK_IOERR;
f7ff39c6
DE
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 */
c90cc42e 439GSocket *GSocket::WaitConnection()
f7ff39c6
DE
440{
441 GSocket *connection;
442 struct sockaddr from;
9e03e02d 443 WX_SOCKLEN_T fromlen = sizeof(from);
f7ff39c6
DE
444 GSocketError err;
445 u_long arg = 1;
446
c90cc42e 447 assert(this);
f7ff39c6
DE
448
449 /* Reenable CONNECTION events */
c90cc42e 450 m_detected &= ~GSOCK_CONNECTION_FLAG;
f7ff39c6
DE
451
452 /* If the socket has already been created, we exit immediately */
c90cc42e 453 if (m_fd == INVALID_SOCKET || !m_server)
f7ff39c6 454 {
c90cc42e 455 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
456 return NULL;
457 }
458
459 /* Create a GSocket object for the new connection */
460 connection = GSocket_new();
461
462 if (!connection)
463 {
c90cc42e 464 m_error = GSOCK_MEMERR;
f7ff39c6
DE
465 return NULL;
466 }
467
468 /* Wait for a connection (with timeout) */
c90cc42e 469 if (Input_Timeout() == GSOCK_TIMEDOUT)
f7ff39c6 470 {
85431efa 471 delete connection;
c90cc42e 472 /* m_error set by _GSocket_Input_Timeout */
f7ff39c6
DE
473 return NULL;
474 }
475
c90cc42e 476 connection->m_fd = accept(m_fd, &from, &fromlen);
f7ff39c6
DE
477
478 if (connection->m_fd == INVALID_SOCKET)
479 {
480 if (WSAGetLastError() == WSAEWOULDBLOCK)
c90cc42e 481 m_error = GSOCK_WOULDBLOCK;
f7ff39c6 482 else
c90cc42e 483 m_error = GSOCK_IOERR;
f7ff39c6 484
85431efa 485 delete connection;
f7ff39c6
DE
486 return NULL;
487 }
488
489 /* Initialize all fields */
948c96ef
DE
490 connection->m_server = false;
491 connection->m_stream = true;
f7ff39c6
DE
492
493 /* Setup the peer address field */
494 connection->m_peer = GAddress_new();
495 if (!connection->m_peer)
496 {
85431efa 497 delete connection;
c90cc42e 498 m_error = GSOCK_MEMERR;
f7ff39c6
DE
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);
85431efa 505 delete connection;
c90cc42e 506 m_error = err;
f7ff39c6
DE
507 return NULL;
508 }
509
510 ioctlsocket(connection->m_fd, FIONBIO, (u_long FAR *) &arg);
c90cc42e 511 gs_gui_functions->Enable_Events(connection);
f7ff39c6
DE
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.
3103e8a9 521* Returns true if the flag was set correctly, false if an error occurred
f7ff39c6
DE
522* (ie, if the parameter was NULL)
523*/
948c96ef 524bool GSocket::SetReusable()
f7ff39c6
DE
525{
526 /* socket must not be null, and must not be in use/already bound */
c90cc42e 527 if (this && m_fd == INVALID_SOCKET) {
948c96ef
DE
528 m_reusable = true;
529 return true;
f7ff39c6 530 }
948c96ef 531 return false;
f7ff39c6
DE
532}
533
60edcf45
VZ
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
f7ff39c6
DE
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
3103e8a9 568 * connection has been successfully established, or one of the error
f7ff39c6
DE
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 */
c90cc42e 587GSocketError GSocket::Connect(GSocketStream stream)
f7ff39c6
DE
588{
589 int ret, err;
590 u_long arg = 1;
591
c90cc42e 592 assert(this);
f7ff39c6
DE
593
594 /* Enable CONNECTION events (needed for nonblocking connections) */
c90cc42e 595 m_detected &= ~GSOCK_CONNECTION_FLAG;
f7ff39c6 596
c90cc42e 597 if (m_fd != INVALID_SOCKET)
f7ff39c6 598 {
c90cc42e 599 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
600 return GSOCK_INVSOCK;
601 }
602
c90cc42e 603 if (!m_peer)
f7ff39c6 604 {
c90cc42e 605 m_error = GSOCK_INVADDR;
f7ff39c6
DE
606 return GSOCK_INVADDR;
607 }
608
609 /* Streamed or dgram socket? */
c90cc42e 610 m_stream = (stream == GSOCK_STREAMED);
948c96ef
DE
611 m_server = false;
612 m_establishing = false;
f7ff39c6
DE
613
614 /* Create the socket */
c90cc42e
DE
615 m_fd = socket(m_peer->m_realfamily,
616 m_stream? SOCK_STREAM : SOCK_DGRAM, 0);
f7ff39c6 617
c90cc42e 618 if (m_fd == INVALID_SOCKET)
f7ff39c6 619 {
c90cc42e 620 m_error = GSOCK_IOERR;
f7ff39c6
DE
621 return GSOCK_IOERR;
622 }
623
c90cc42e
DE
624 ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
625 gs_gui_functions->Enable_Events(this);
f7ff39c6 626
716a5baa
KH
627 // If the reuse flag is set, use the applicable socket reuse flag
628 if (m_reusable)
629 {
28bf2f3c 630 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
716a5baa
KH
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
f7ff39c6 639 /* Connect it to the peer address, with a timeout (see below) */
c90cc42e 640 ret = connect(m_fd, m_peer->m_addr, m_peer->m_len);
f7ff39c6
DE
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 */
c90cc42e 651 if ((err == WSAEWOULDBLOCK) && (!m_non_blocking))
f7ff39c6 652 {
c90cc42e 653 err = Connect_Timeout();
f7ff39c6
DE
654
655 if (err != GSOCK_NOERROR)
656 {
c90cc42e
DE
657 Close();
658 /* m_error is set in _GSocket_Connect_Timeout */
f7ff39c6
DE
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 */
c90cc42e 670 if ((err == WSAEWOULDBLOCK) && (m_non_blocking))
f7ff39c6 671 {
948c96ef 672 m_establishing = true;
c90cc42e 673 m_error = GSOCK_WOULDBLOCK;
f7ff39c6
DE
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 */
c90cc42e
DE
680 Close();
681 m_error = GSOCK_IOERR;
f7ff39c6
DE
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 */
c90cc42e 701GSocketError GSocket::SetNonOriented()
f7ff39c6
DE
702{
703 u_long arg = 1;
704
c90cc42e 705 assert(this);
f7ff39c6 706
c90cc42e 707 if (m_fd != INVALID_SOCKET)
f7ff39c6 708 {
c90cc42e 709 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
710 return GSOCK_INVSOCK;
711 }
712
c90cc42e 713 if (!m_local)
f7ff39c6 714 {
c90cc42e 715 m_error = GSOCK_INVADDR;
f7ff39c6
DE
716 return GSOCK_INVADDR;
717 }
718
719 /* Initialize all fields */
948c96ef
DE
720 m_stream = false;
721 m_server = false;
f7ff39c6
DE
722
723 /* Create the socket */
c90cc42e 724 m_fd = socket(m_local->m_realfamily, SOCK_DGRAM, 0);
f7ff39c6 725
c90cc42e 726 if (m_fd == INVALID_SOCKET)
f7ff39c6 727 {
c90cc42e 728 m_error = GSOCK_IOERR;
f7ff39c6
DE
729 return GSOCK_IOERR;
730 }
731
c90cc42e
DE
732 ioctlsocket(m_fd, FIONBIO, (u_long FAR *) &arg);
733 gs_gui_functions->Enable_Events(this);
f7ff39c6 734
28bf2f3c
VZ
735 if (m_reusable)
736 {
737 setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&arg, sizeof(arg));
738 }
60edcf45 739 if (m_broadcast)
f7ff39c6 740 {
60edcf45
VZ
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 }
f7ff39c6
DE
757 }
758
759 return GSOCK_NOERROR;
760}
761
762/* Generic IO */
763
764/* Like recv(), send(), ... */
c90cc42e 765int GSocket::Read(char *buffer, int size)
f7ff39c6
DE
766{
767 int ret;
768
c90cc42e 769 assert(this);
f7ff39c6
DE
770
771 /* Reenable INPUT events */
c90cc42e 772 m_detected &= ~GSOCK_INPUT_FLAG;
f7ff39c6 773
c90cc42e 774 if (m_fd == INVALID_SOCKET || m_server)
f7ff39c6 775 {
c90cc42e 776 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
777 return -1;
778 }
779
780 /* If the socket is blocking, wait for data (with a timeout) */
c90cc42e 781 if (Input_Timeout() == GSOCK_TIMEDOUT)
976abb72
VZ
782 {
783 m_error = GSOCK_TIMEDOUT;
f7ff39c6 784 return -1;
976abb72 785 }
f7ff39c6
DE
786
787 /* Read the data */
c90cc42e
DE
788 if (m_stream)
789 ret = Recv_Stream(buffer, size);
f7ff39c6 790 else
c90cc42e 791 ret = Recv_Dgram(buffer, size);
f7ff39c6
DE
792
793 if (ret == SOCKET_ERROR)
794 {
795 if (WSAGetLastError() != WSAEWOULDBLOCK)
c90cc42e 796 m_error = GSOCK_IOERR;
f7ff39c6 797 else
c90cc42e 798 m_error = GSOCK_WOULDBLOCK;
f7ff39c6
DE
799 return -1;
800 }
801
802 return ret;
803}
804
c90cc42e 805int GSocket::Write(const char *buffer, int size)
f7ff39c6
DE
806{
807 int ret;
808
c90cc42e 809 assert(this);
f7ff39c6 810
c90cc42e 811 if (m_fd == INVALID_SOCKET || m_server)
f7ff39c6 812 {
c90cc42e 813 m_error = GSOCK_INVSOCK;
f7ff39c6
DE
814 return -1;
815 }
816
817 /* If the socket is blocking, wait for writability (with a timeout) */
c90cc42e 818 if (Output_Timeout() == GSOCK_TIMEDOUT)
f7ff39c6
DE
819 return -1;
820
821 /* Write the data */
c90cc42e
DE
822 if (m_stream)
823 ret = Send_Stream(buffer, size);
f7ff39c6 824 else
c90cc42e 825 ret = Send_Dgram(buffer, size);
f7ff39c6
DE
826
827 if (ret == SOCKET_ERROR)
828 {
829 if (WSAGetLastError() != WSAEWOULDBLOCK)
c90cc42e 830 m_error = GSOCK_IOERR;
f7ff39c6 831 else
c90cc42e 832 m_error = GSOCK_WOULDBLOCK;
f7ff39c6
DE
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 */
c90cc42e 839 m_detected &= ~GSOCK_OUTPUT_FLAG;
f7ff39c6
DE
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 */
c90cc42e 853GSocketEventFlags GSocket::Select(GSocketEventFlags flags)
f7ff39c6 854{
c90cc42e 855 if (!gs_gui_functions->CanUseEventLoop())
f7ff39c6
DE
856 {
857 GSocketEventFlags result = 0;
858 fd_set readfds;
859 fd_set writefds;
860 fd_set exceptfds;
861
c90cc42e 862 assert(this);
f7ff39c6
DE
863
864 FD_ZERO(&readfds);
865 FD_ZERO(&writefds);
866 FD_ZERO(&exceptfds);
c90cc42e 867 FD_SET(m_fd, &readfds);
f7ff39c6 868 if (flags & GSOCK_OUTPUT_FLAG || flags & GSOCK_CONNECTION_FLAG)
c90cc42e
DE
869 FD_SET(m_fd, &writefds);
870 FD_SET(m_fd, &exceptfds);
f7ff39c6
DE
871
872 /* Check 'sticky' CONNECTION flag first */
c90cc42e 873 result |= (GSOCK_CONNECTION_FLAG & m_detected);
f7ff39c6
DE
874
875 /* If we have already detected a LOST event, then don't try
876 * to do any further processing.
877 */
c90cc42e 878 if ((m_detected & GSOCK_LOST_FLAG) != 0)
f7ff39c6 879 {
948c96ef 880 m_establishing = false;
f7ff39c6
DE
881
882 return (GSOCK_LOST_FLAG & flags);
883 }
884
885 /* Try select now */
c90cc42e
DE
886 if (select(m_fd + 1, &readfds, &writefds, &exceptfds,
887 &m_timeout) <= 0)
f7ff39c6
DE
888 {
889 /* What to do here? */
890 return (result & flags);
891 }
892
b74865fa
KH
893 /* Check for exceptions and errors */
894 if (FD_ISSET(m_fd, &exceptfds))
f7ff39c6 895 {
b74865fa
KH
896 m_establishing = false;
897 m_detected = GSOCK_LOST_FLAG;
f7ff39c6 898
b74865fa
KH
899 /* LOST event: Abort any further processing */
900 return (GSOCK_LOST_FLAG & flags);
901 }
f7ff39c6 902
b74865fa
KH
903 /* Check for readability */
904 if (FD_ISSET(m_fd, &readfds))
905 {
906 result |= GSOCK_INPUT_FLAG;
907
908 if (m_server && m_stream)
f4322df6
VZ
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
b74865fa
KH
912 this kind of sockets, as we can only Accept() from them. */
913 result |= GSOCK_CONNECTION_FLAG;
914 m_detected |= GSOCK_CONNECTION_FLAG;
f7ff39c6
DE
915 }
916 }
917
918 /* Check for writability */
c90cc42e 919 if (FD_ISSET(m_fd, &writefds))
f7ff39c6 920 {
c90cc42e 921 if (m_establishing && !m_server)
f7ff39c6
DE
922 {
923 int error;
9e03e02d 924 WX_SOCKLEN_T len = sizeof(error);
f7ff39c6 925
948c96ef 926 m_establishing = false;
f7ff39c6 927
c90cc42e 928 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
f7ff39c6
DE
929
930 if (error)
931 {
c90cc42e 932 m_detected = GSOCK_LOST_FLAG;
f7ff39c6
DE
933
934 /* LOST event: Abort any further processing */
935 return (GSOCK_LOST_FLAG & flags);
936 }
937 else
938 {
939 result |= GSOCK_CONNECTION_FLAG;
c90cc42e 940 m_detected |= GSOCK_CONNECTION_FLAG;
f7ff39c6
DE
941 }
942 }
943 else
944 {
945 result |= GSOCK_OUTPUT_FLAG;
946 }
947 }
948
f7ff39c6
DE
949 return (result & flags);
950 }
951 else /* USE_GUI() */
952 {
c90cc42e
DE
953 assert(this);
954 return flags & m_detected;
f7ff39c6
DE
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 */
c90cc42e 964void GSocket::SetNonBlocking(bool non_block)
f7ff39c6 965{
c90cc42e 966 assert(this);
f7ff39c6 967
c90cc42e 968 m_non_blocking = non_block;
f7ff39c6
DE
969}
970
971/* GSocket_SetTimeout:
972 * Sets the timeout for blocking calls. Time is expressed in
973 * milliseconds.
974 */
c90cc42e 975void GSocket::SetTimeout(unsigned long millis)
f7ff39c6 976{
c90cc42e 977 assert(this);
f7ff39c6 978
c90cc42e
DE
979 m_timeout.tv_sec = (millis / 1000);
980 m_timeout.tv_usec = (millis % 1000) * 1000;
f7ff39c6
DE
981}
982
983/* GSocket_GetError:
3103e8a9 984 * Returns the last error occurred for this socket. Note that successful
f7ff39c6
DE
985 * operations do not clear this back to GSOCK_NOERROR, so use it only
986 * after an error.
987 */
a4506848 988GSocketError WXDLLIMPEXP_NET GSocket::GetError()
f7ff39c6 989{
c90cc42e 990 assert(this);
f7ff39c6 991
c90cc42e 992 return m_error;
f7ff39c6
DE
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:
3103e8a9 1009 * Connection successfully established, for client sockets, or incoming
f7ff39c6
DE
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 */
c90cc42e 1025void GSocket::SetCallback(GSocketEventFlags flags,
f7ff39c6
DE
1026 GSocketCallback callback, char *cdata)
1027{
1028 int count;
1029
c90cc42e 1030 assert(this);
f7ff39c6
DE
1031
1032 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1033 {
1034 if ((flags & (1 << count)) != 0)
1035 {
c90cc42e
DE
1036 m_cbacks[count] = callback;
1037 m_data[count] = cdata;
f7ff39c6
DE
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 */
c90cc42e 1046void GSocket::UnsetCallback(GSocketEventFlags flags)
f7ff39c6
DE
1047{
1048 int count;
1049
c90cc42e 1050 assert(this);
f7ff39c6
DE
1051
1052 for (count = 0; count < GSOCK_MAX_EVENT; count++)
1053 {
1054 if ((flags & (1 << count)) != 0)
1055 {
c90cc42e
DE
1056 m_cbacks[count] = NULL;
1057 m_data[count] = NULL;
f7ff39c6
DE
1058 }
1059 }
1060}
1061
c90cc42e 1062GSocketError GSocket::GetSockOpt(int level, int optname,
f7ff39c6
DE
1063 void *optval, int *optlen)
1064{
c90cc42e 1065 if (getsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
f7ff39c6
DE
1066 {
1067 return GSOCK_NOERROR;
1068 }
1069 return GSOCK_OPTERR;
1070}
1071
c90cc42e 1072GSocketError GSocket::SetSockOpt(int level, int optname,
f7ff39c6
DE
1073 const void *optval, int optlen)
1074{
c90cc42e 1075 if (setsockopt(m_fd, level, optname, (char*)optval, optlen) == 0)
f7ff39c6
DE
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 */
c90cc42e 1088GSocketError GSocket::Input_Timeout()
f7ff39c6
DE
1089{
1090 fd_set readfds;
1091
c90cc42e 1092 if (!m_non_blocking)
f7ff39c6
DE
1093 {
1094 FD_ZERO(&readfds);
c90cc42e
DE
1095 FD_SET(m_fd, &readfds);
1096 if (select(0, &readfds, NULL, NULL, &m_timeout) == 0)
f7ff39c6 1097 {
c90cc42e 1098 m_error = GSOCK_TIMEDOUT;
f7ff39c6
DE
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 */
c90cc42e 1109GSocketError GSocket::Output_Timeout()
f7ff39c6
DE
1110{
1111 fd_set writefds;
1112
c90cc42e 1113 if (!m_non_blocking)
f7ff39c6
DE
1114 {
1115 FD_ZERO(&writefds);
c90cc42e
DE
1116 FD_SET(m_fd, &writefds);
1117 if (select(0, NULL, &writefds, NULL, &m_timeout) == 0)
f7ff39c6 1118 {
c90cc42e 1119 m_error = GSOCK_TIMEDOUT;
f7ff39c6
DE
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 */
c90cc42e 1130GSocketError GSocket::Connect_Timeout()
f7ff39c6
DE
1131{
1132 fd_set writefds;
1133 fd_set exceptfds;
1134
1135 FD_ZERO(&writefds);
1136 FD_ZERO(&exceptfds);
c90cc42e
DE
1137 FD_SET(m_fd, &writefds);
1138 FD_SET(m_fd, &exceptfds);
1139 if (select(0, NULL, &writefds, &exceptfds, &m_timeout) == 0)
f7ff39c6 1140 {
c90cc42e 1141 m_error = GSOCK_TIMEDOUT;
f7ff39c6
DE
1142 return GSOCK_TIMEDOUT;
1143 }
c90cc42e 1144 if (!FD_ISSET(m_fd, &writefds))
f7ff39c6 1145 {
c90cc42e 1146 m_error = GSOCK_IOERR;
f7ff39c6
DE
1147 return GSOCK_IOERR;
1148 }
1149
1150 return GSOCK_NOERROR;
1151}
1152
c90cc42e 1153int GSocket::Recv_Stream(char *buffer, int size)
f7ff39c6 1154{
c90cc42e 1155 return recv(m_fd, buffer, size, 0);
f7ff39c6
DE
1156}
1157
c90cc42e 1158int GSocket::Recv_Dgram(char *buffer, int size)
f7ff39c6
DE
1159{
1160 struct sockaddr from;
9e03e02d 1161 WX_SOCKLEN_T fromlen = sizeof(from);
f7ff39c6
DE
1162 int ret;
1163 GSocketError err;
1164
c90cc42e 1165 ret = recvfrom(m_fd, buffer, size, 0, &from, &fromlen);
f7ff39c6
DE
1166
1167 if (ret == SOCKET_ERROR)
1168 return SOCKET_ERROR;
1169
1170 /* Translate a system address into a GSocket address */
c90cc42e 1171 if (!m_peer)
f7ff39c6 1172 {
c90cc42e
DE
1173 m_peer = GAddress_new();
1174 if (!m_peer)
f7ff39c6 1175 {
c90cc42e 1176 m_error = GSOCK_MEMERR;
f7ff39c6
DE
1177 return -1;
1178 }
1179 }
c90cc42e 1180 err = _GAddress_translate_from(m_peer, &from, fromlen);
f7ff39c6
DE
1181 if (err != GSOCK_NOERROR)
1182 {
c90cc42e
DE
1183 GAddress_destroy(m_peer);
1184 m_peer = NULL;
1185 m_error = err;
f7ff39c6
DE
1186 return -1;
1187 }
1188
1189 return ret;
1190}
1191
c90cc42e 1192int GSocket::Send_Stream(const char *buffer, int size)
f7ff39c6 1193{
c90cc42e 1194 return send(m_fd, buffer, size, 0);
f7ff39c6
DE
1195}
1196
c90cc42e 1197int GSocket::Send_Dgram(const char *buffer, int size)
f7ff39c6
DE
1198{
1199 struct sockaddr *addr;
1200 int len, ret;
1201 GSocketError err;
1202
c90cc42e 1203 if (!m_peer)
f7ff39c6 1204 {
c90cc42e 1205 m_error = GSOCK_INVADDR;
f7ff39c6
DE
1206 return -1;
1207 }
1208
c90cc42e 1209 err = _GAddress_translate_to(m_peer, &addr, &len);
f7ff39c6
DE
1210 if (err != GSOCK_NOERROR)
1211 {
c90cc42e 1212 m_error = err;
f7ff39c6
DE
1213 return -1;
1214 }
1215
c90cc42e 1216 ret = sendto(m_fd, buffer, size, 0, addr, len);
f7ff39c6
DE
1217
1218 /* Frees memory allocated by _GAddress_translate_to */
1219 free(addr);
1220
1221 return ret;
1222}
1223
c90cc42e
DE
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
f7ff39c6
DE
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
60edcf45
VZ
1452GSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
1453{
1454 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
1455}
1456
f7ff39c6
DE
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);
d0ee33f5 1472 addr->s_addr = htonl(hostaddr);
f7ff39c6
DE
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
907173e5 1588GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *WXUNUSED(path))
f7ff39c6 1589{
f7ff39c6
DE
1590 assert (address != NULL);
1591 address->m_error = GSOCK_INVADDR;
1592 return GSOCK_INVADDR;
1593}
1594
907173e5 1595GSocketError GAddress_UNIX_GetPath(GAddress *address, char *WXUNUSED(path), size_t WXUNUSED(sbuf))
f7ff39c6 1596{
f7ff39c6
DE
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__) */