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