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