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