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