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