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