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