]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gsocket.c
Process pending events before deleting pending objects, and do it
[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
VZ
14/* including rasasync.h (included from windows.h itself included from
15 * wx/setup.h and/or winsock.h results in this warning for
16 * RPCNOTIFICATION_ROUTINE
17 */
18#ifdef _MSC_VER
19# pragma warning(disable:4115) /* named type definition in parentheses */
20#endif
21
2f7c2af5 22#ifndef __GSOCKET_STANDALONE__
9bbd7ba3 23#include "wx/setup.h"
0ce742cf
GRG
24#endif
25
26#if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__)
27
0ce742cf 28#ifndef __GSOCKET_STANDALONE__
ed2eb9af
GRG
29# include "wx/msw/gsockmsw.h"
30# include "wx/gsocket.h"
9bbd7ba3 31#else
ed2eb9af
GRG
32# include "gsockmsw.h"
33# include "gsocket.h"
34#endif /* __GSOCKET_STANDALONE__ */
9bbd7ba3 35
ed2eb9af
GRG
36/* redefine some GUI-only functions to do nothing in console mode */
37#if defined(wxUSE_GUI) && !wxUSE_GUI
38# define _GSocket_GUI_Init(socket) 1
39# define _GSocket_GUI_Destroy(socket)
40# define _GSocket_Enable_Events(socket)
41# define _GSocket_Disable_Events(socket)
42#endif /* wxUSE_GUI */
9bbd7ba3 43
9bbd7ba3 44
9bbd7ba3
GRG
45#include <assert.h>
46#include <string.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <stddef.h>
50#include <ctype.h>
8a9c2246 51
9bbd7ba3
GRG
52#include <winsock.h>
53
8a9c2246
VZ
54#ifdef _MSC_VER
55# pragma warning(default:4115) /* named type definition in parentheses */
56#endif
57
c42404a5
VZ
58/* if we use configure for MSW SOCKLEN_T will be already defined */
59#ifndef SOCKLEN_T
ed2eb9af 60# define SOCKLEN_T int
c42404a5
VZ
61#endif
62
ed2eb9af 63/* using FD_SET results in this warning */
378d2bd3 64#ifdef _MSC_VER
ed2eb9af
GRG
65# pragma warning(disable:4127) /* conditional expression is constant */
66#endif
378d2bd3 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
GRG
99 free(socket);
100 return 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
GRG
770 */
771void GSocket_SetNonBlocking(GSocket *socket, bool non_block)
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
1018/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY
1019 * or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it initalizes address
1020 * to be a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
1021 */
1022#define CHECK_ADDRESS(address, family, retval) \
1023{ \
1024 if (address->m_family == GSOCK_NOFAMILY) \
1025 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) \
1026 return address->m_error; \
1027 if (address->m_family != GSOCK_##family) \
1028 { \
1029 address->m_error = GSOCK_INVADDR; \
1030 return retval; \
1031 } \
1032}
1033
da051b23 1034GAddress *GAddress_new(void)
9bbd7ba3
GRG
1035{
1036 GAddress *address;
1037
1038 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1039 return NULL;
1040
1041 address->m_family = GSOCK_NOFAMILY;
1042 address->m_addr = NULL;
1043 address->m_len = 0;
1044
1045 return address;
1046}
1047
1048GAddress *GAddress_copy(GAddress *address)
1049{
1050 GAddress *addr2;
1051
1052 assert(address != NULL);
1053
1054 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
1055 return NULL;
1056
1057 memcpy(addr2, address, sizeof(GAddress));
1058
1059 if (address->m_addr)
1060 {
1061 addr2->m_addr = (struct sockaddr *) malloc(addr2->m_len);
1062 if (addr2->m_addr == NULL)
1063 {
1064 free(addr2);
1065 return NULL;
1066 }
1067 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
1068 }
1069
1070 return addr2;
1071}
1072
1073void GAddress_destroy(GAddress *address)
1074{
1075 assert(address != NULL);
1076
8a9c2246 1077 free(address->m_addr);
9bbd7ba3
GRG
1078 free(address);
1079}
1080
1081void GAddress_SetFamily(GAddress *address, GAddressType type)
1082{
1083 assert(address != NULL);
1084
1085 address->m_family = type;
1086}
1087
1088GAddressType GAddress_GetFamily(GAddress *address)
1089{
1090 assert(address != NULL);
1091
1092 return address->m_family;
1093}
1094
1095GSocketError _GAddress_translate_from(GAddress *address,
1096 struct sockaddr *addr, int len)
1097{
1098 address->m_realfamily = addr->sa_family;
1099 switch (addr->sa_family)
1100 {
1101 case AF_INET:
1102 address->m_family = GSOCK_INET;
1103 break;
1104 case AF_UNIX:
1105 address->m_family = GSOCK_UNIX;
1106 break;
1107#ifdef AF_INET6
1108 case AF_INET6:
1109 address->m_family = GSOCK_INET6;
1110 break;
1111#endif
1112 default:
1113 {
1114 address->m_error = GSOCK_INVOP;
1115 return GSOCK_INVOP;
1116 }
1117 }
1118
1119 if (address->m_addr)
1120 free(address->m_addr);
1121
1122 address->m_len = len;
1123 address->m_addr = (struct sockaddr *) malloc(len);
1124
1125 if (address->m_addr == NULL)
1126 {
1127 address->m_error = GSOCK_MEMERR;
1128 return GSOCK_MEMERR;
1129 }
1130 memcpy(address->m_addr, addr, len);
1131
1132 return GSOCK_NOERROR;
1133}
1134
1135GSocketError _GAddress_translate_to(GAddress *address,
1136 struct sockaddr **addr, int *len)
1137{
1138 if (!address->m_addr)
1139 {
1140 address->m_error = GSOCK_INVADDR;
1141 return GSOCK_INVADDR;
1142 }
1143
1144 *len = address->m_len;
1145 *addr = (struct sockaddr *) malloc(address->m_len);
1146 if (*addr == NULL)
1147 {
1148 address->m_error = GSOCK_MEMERR;
1149 return GSOCK_MEMERR;
1150 }
1151
1152 memcpy(*addr, address->m_addr, address->m_len);
1153 return GSOCK_NOERROR;
1154}
1155
1156/*
1157 * -------------------------------------------------------------------------
1158 * Internet address family
1159 * -------------------------------------------------------------------------
1160 */
1161
1162GSocketError _GAddress_Init_INET(GAddress *address)
1163{
9bf10d6b 1164 address->m_len = sizeof(struct sockaddr_in);
9bbd7ba3
GRG
1165 address->m_addr = (struct sockaddr *) malloc(address->m_len);
1166 if (address->m_addr == NULL)
1167 {
1168 address->m_error = GSOCK_MEMERR;
1169 return GSOCK_MEMERR;
1170 }
1171
9bbd7ba3
GRG
1172 address->m_family = GSOCK_INET;
1173 address->m_realfamily = PF_INET;
1174 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
9bf10d6b 1175 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
9bbd7ba3
GRG
1176
1177 return GSOCK_NOERROR;
1178}
1179
1180GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1181{
1182 struct hostent *he;
1183 struct in_addr *addr;
1184
1185 assert(address != NULL);
1186
1187 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1188
1189 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1190
1191 addr->s_addr = inet_addr(hostname);
b661e675 1192
9bbd7ba3
GRG
1193 /* If it is a numeric host name, convert it now */
1194 if (addr->s_addr == INADDR_NONE)
1195 {
1196 struct in_addr *array_addr;
1197
1198 /* It is a real name, we solve it */
1199 if ((he = gethostbyname(hostname)) == NULL)
1200 {
9bf10d6b 1201 /* addr->s_addr = INADDR_NONE just done by inet_addr() above */
9bbd7ba3
GRG
1202 address->m_error = GSOCK_NOHOST;
1203 return GSOCK_NOHOST;
1204 }
1205 array_addr = (struct in_addr *) *(he->h_addr_list);
1206 addr->s_addr = array_addr[0].s_addr;
1207 }
1208 return GSOCK_NOERROR;
1209}
1210
9bf10d6b
GRG
1211GSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1212{
1213 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1214}
1215
9bbd7ba3
GRG
1216GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1217 unsigned long hostaddr)
1218{
1219 struct in_addr *addr;
1220
1221 assert(address != NULL);
1222
1223 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1224
1225 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1226 addr->s_addr = hostaddr;
1227
1228 return GSOCK_NOERROR;
1229}
1230
1231GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1232 const char *protocol)
1233{
1234 struct servent *se;
1235 struct sockaddr_in *addr;
1236
1237 assert(address != NULL);
1238 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1239
1240 if (!port)
1241 {
1242 address->m_error = GSOCK_INVPORT;
9bf10d6b 1243 return GSOCK_INVPORT;
9bbd7ba3 1244 }
b661e675 1245
9bbd7ba3
GRG
1246 se = getservbyname(port, protocol);
1247 if (!se)
1248 {
1249 if (isdigit(port[0]))
1250 {
1251 int port_int;
1252
1253 port_int = atoi(port);
1254 addr = (struct sockaddr_in *)address->m_addr;
aa3981f2 1255 addr->sin_port = htons((u_short) port_int);
9bbd7ba3
GRG
1256 return GSOCK_NOERROR;
1257 }
1258
1259 address->m_error = GSOCK_INVPORT;
1260 return GSOCK_INVPORT;
1261 }
1262
1263 addr = (struct sockaddr_in *)address->m_addr;
1264 addr->sin_port = se->s_port;
1265
1266 return GSOCK_NOERROR;
1267}
1268
1269GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1270{
1271 struct sockaddr_in *addr;
1272
1273 assert(address != NULL);
1274 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
b661e675 1275
9bbd7ba3
GRG
1276 addr = (struct sockaddr_in *)address->m_addr;
1277 addr->sin_port = htons(port);
1278
1279 return GSOCK_NOERROR;
1280}
1281
1282GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1283{
1284 struct hostent *he;
1285 char *addr_buf;
1286 struct sockaddr_in *addr;
1287
b661e675 1288 assert(address != NULL);
9bbd7ba3
GRG
1289 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1290
1291 addr = (struct sockaddr_in *)address->m_addr;
1292 addr_buf = (char *)&(addr->sin_addr);
1293
1294 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1295 if (he == NULL)
1296 {
1297 address->m_error = GSOCK_NOHOST;
1298 return GSOCK_NOHOST;
1299 }
1300
1301 strncpy(hostname, he->h_name, sbuf);
1302
1303 return GSOCK_NOERROR;
1304}
1305
1306unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1307{
1308 struct sockaddr_in *addr;
1309
b661e675
RD
1310 assert(address != NULL);
1311 CHECK_ADDRESS(address, INET, 0);
9bbd7ba3
GRG
1312
1313 addr = (struct sockaddr_in *)address->m_addr;
1314
1315 return addr->sin_addr.s_addr;
1316}
1317
1318unsigned short GAddress_INET_GetPort(GAddress *address)
1319{
1320 struct sockaddr_in *addr;
1321
b661e675
RD
1322 assert(address != NULL);
1323 CHECK_ADDRESS(address, INET, 0);
9bbd7ba3
GRG
1324
1325 addr = (struct sockaddr_in *)address->m_addr;
1326 return ntohs(addr->sin_port);
1327}
1328
1329/*
1330 * -------------------------------------------------------------------------
1331 * Unix address family
1332 * -------------------------------------------------------------------------
1333 */
1334
378d2bd3
VZ
1335#ifdef _MSC_VER
1336 #pragma warning(disable:4100) /* unreferenced formal parameter */
1337#endif /* Visual C++ */
1338
9bbd7ba3
GRG
1339GSocketError _GAddress_Init_UNIX(GAddress *address)
1340{
1341 assert (address != NULL);
1342 address->m_error = GSOCK_INVADDR;
1343 return GSOCK_INVADDR;
1344}
1345
1346GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1347{
1348 assert (address != NULL);
1349 address->m_error = GSOCK_INVADDR;
1350 return GSOCK_INVADDR;
1351}
1352
1353GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1354{
1355 assert (address != NULL);
1356 address->m_error = GSOCK_INVADDR;
1357 return GSOCK_INVADDR;
1358}
1359
a497618a 1360#else /* !wxUSE_SOCKETS */
9bbd7ba3 1361
a497618a 1362/*
9bf10d6b 1363 * Translation unit shouldn't be empty, so include this typedef to make the
a497618a
VZ
1364 * compiler (VC++ 6.0, for example) happy
1365 */
1366typedef (*wxDummy)();
9bbd7ba3 1367
a497618a 1368#endif /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */