]> git.saurik.com Git - wxWidgets.git/blame - src/unix/gsocket.c
unused parameter warnings suppressed
[wxWidgets.git] / src / unix / gsocket.c
CommitLineData
a324a7bc
GL
1/* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Purpose: GSocket main Unix file
5 * CVSID: $Id$
a324a7bc
GL
6 * -------------------------------------------------------------------------
7 */
8
813c20a6
VZ
9#include "wx/setup.h"
10
11#if wxUSE_SOCKETS
12
a324a7bc
GL
13#include <assert.h>
14#include <sys/ioctl.h>
efee48a0 15#include <sys/types.h>
a324a7bc
GL
16#ifdef vms
17#include <socket.h>
18#else
19#include <sys/socket.h>
20#endif
21#include <sys/un.h>
a324a7bc
GL
22#include <sys/time.h>
23#include <netinet/in.h>
24#include <arpa/inet.h>
25#include <netdb.h>
9592b687 26#include <errno.h>
a324a7bc
GL
27
28#include <string.h>
29#include <unistd.h>
30#include <stdio.h>
31#include <stdlib.h>
552e8bf8 32#include <stddef.h>
9b61f868 33#include <ctype.h>
a324a7bc
GL
34
35#ifdef sun
f61815af 36# include <sys/filio.h>
a324a7bc
GL
37#endif
38
39#ifdef sgi
f61815af 40# include <bstring.h>
a324a7bc
GL
41#endif
42
43#include <signal.h>
5a96d2f4 44
ca17eff3 45#include "wx/gsocket.h"
533c7161 46#include "wx/unix/gsockunx.h"
a324a7bc 47
efee48a0 48#ifndef SOCKLEN_T
5a96d2f4
GL
49
50#ifdef __GLIBC__
51# if __GLIBC__ == 2
52# define SOCKLEN_T socklen_t
53# endif
54#else
55# define SOCKLEN_T int
56#endif
57
efee48a0
KB
58#endif
59
aa6d9706
GL
60#define MASK_SIGNAL() \
61{ \
62 void (*old_handler)(int); \
63\
64 old_handler = signal(SIGPIPE, SIG_IGN);
65
66#define UNMASK_SIGNAL() \
67 signal(SIGPIPE, old_handler); \
68}
69
70#define ENABLE_TIMEOUT(socket) \
71{ \
72 struct itimerval old_ival, new_ival; \
73 void (*old_timer_sig)(int); \
74\
75 old_timer_sig = signal(SIGALRM, SIG_DFL); \
76 siginterrupt(SIGALRM, 1); \
77 new_ival.it_value.tv_sec = socket->m_timeout / 1000; \
78 new_ival.it_value.tv_usec = (socket->m_timeout % 1000) * 1000; \
79 new_ival.it_interval.tv_sec = 0; \
80 new_ival.it_interval.tv_usec = 0; \
81 setitimer(ITIMER_REAL, &new_ival, &old_ival);
82
83#define DISABLE_TIMEOUT(socket) \
84 signal(SIGALRM, old_timer_sig); \
85 siginterrupt(SIGALRM, 0); \
86 setitimer(ITIMER_REAL, &old_ival, NULL); \
87}
54e575f9 88
a58d5df4
GL
89/* Global initialisers */
90
31989b0b 91bool GSocket_Init()
a58d5df4 92{
31989b0b 93 return TRUE;
a58d5df4
GL
94}
95
96void GSocket_Cleanup()
97{
98}
99
a324a7bc
GL
100/* Constructors / Destructors */
101
102GSocket *GSocket_new()
103{
104 int i;
105 GSocket *socket;
106
107 socket = (GSocket *)malloc(sizeof(GSocket));
108
e00f35bb
GL
109 if (socket == NULL)
110 return NULL;
111
a324a7bc
GL
112 socket->m_fd = -1;
113 for (i=0;i<GSOCK_MAX_EVENT;i++) {
98781fa3 114 socket->m_cbacks[i] = NULL;
a324a7bc
GL
115 socket->m_iocalls[i] = FALSE;
116 }
117 socket->m_local = NULL;
118 socket->m_peer = NULL;
119 socket->m_error = GSOCK_NOERROR;
ef25e638
GRG
120 socket->m_server = FALSE;
121 socket->m_stream = TRUE;
122 socket->m_gui_dependent = NULL;
123 socket->m_non_blocking = FALSE;
39b91eca 124 socket->m_timeout = 10*60*1000;
ef25e638 125 /* 10 minutes * 60 sec * 1000 millisec */
aa6d9706 126 socket->m_establishing = FALSE;
a324a7bc 127
31989b0b 128 /* We initialize the GUI specific entries here */
a324a7bc
GL
129 _GSocket_GUI_Init(socket);
130
131 return socket;
132}
133
134void GSocket_destroy(GSocket *socket)
135{
136 assert(socket != NULL);
137
31989b0b 138 /* First, we check that the socket is really shutdowned */
a324a7bc
GL
139 if (socket->m_fd != -1)
140 GSocket_Shutdown(socket);
141
31989b0b 142 /* We destroy GUI specific variables */
dbd300df
GL
143 _GSocket_GUI_Destroy(socket);
144
31989b0b 145 /* We destroy private addresses */
a324a7bc
GL
146 if (socket->m_local)
147 GAddress_destroy(socket->m_local);
148
149 if (socket->m_peer)
150 GAddress_destroy(socket->m_peer);
151
31989b0b 152 /* We destroy socket itself */
a324a7bc
GL
153 free(socket);
154}
155
156void GSocket_Shutdown(GSocket *socket)
157{
158 int evt;
159
160 assert(socket != NULL);
161
31989b0b 162 /* If socket has been created, we shutdown it */
a324a7bc 163 if (socket->m_fd != -1) {
533c7161 164 shutdown(socket->m_fd, 2);
a324a7bc
GL
165 close(socket->m_fd);
166 socket->m_fd = -1;
167 }
168
31989b0b 169 /* We also disable GUI callbacks */
a324a7bc 170 for (evt=0;evt<GSOCK_MAX_EVENT;evt++)
39b91eca 171 _GSocket_Uninstall_Callback(socket, evt);
a324a7bc
GL
172}
173
174/* Address handling */
175
176GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
177{
5a96d2f4
GL
178 assert(socket != NULL);
179
31989b0b
GL
180 if ((socket->m_fd != -1 && !socket->m_server)) {
181 socket->m_error = GSOCK_INVSOCK;
a324a7bc 182 return GSOCK_INVSOCK;
31989b0b 183 }
a324a7bc 184
31989b0b
GL
185 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
186 socket->m_error = GSOCK_INVADDR;
a324a7bc 187 return GSOCK_INVADDR;
31989b0b 188 }
a324a7bc
GL
189
190 if (socket->m_local)
191 GAddress_destroy(socket->m_local);
192
193 socket->m_local = GAddress_copy(address);
194
195 return GSOCK_NOERROR;
196}
197
198GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
199{
5a96d2f4 200 assert(socket != NULL);
a324a7bc
GL
201
202 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
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;
efee48a0 219 SOCKLEN_T size;
aa6d9706 220 GSocketError err;
a324a7bc
GL
221
222 assert(socket != NULL);
223
224 if (socket->m_local)
225 return GAddress_copy(socket->m_local);
226
227 if (socket->m_fd == -1) {
228 socket->m_error = GSOCK_INVSOCK;
229 return NULL;
230 }
231
232 size = sizeof(addr);
233
234 if (getsockname(socket->m_fd, &addr, &size) < 0) {
235 socket->m_error = GSOCK_IOERR;
236 return NULL;
237 }
238
239 address = GAddress_new();
e00f35bb
GL
240 if (address == NULL) {
241 socket->m_error = GSOCK_MEMERR;
242 return NULL;
243 }
aa6d9706
GL
244 socket->m_error = _GAddress_translate_from(address, &addr, size);
245 if (socket->m_error != GSOCK_NOERROR) {
e00f35bb
GL
246 GAddress_destroy(address);
247 return NULL;
248 }
a324a7bc
GL
249
250 return address;
251}
252
253GAddress *GSocket_GetPeer(GSocket *socket)
254{
255 assert(socket != NULL);
256
257 if (socket->m_peer)
258 return GAddress_copy(socket->m_peer);
259
260 return NULL;
261}
262
263/* Server specific parts */
264
2f7c2af5
GRG
265/* GSocket_SetServer:
266 * Sets up the socket as a server. It uses the "Local" field of GSocket.
267 * "Local" must be set by GSocket_SetLocal() before GSocket_SetServer()
268 * is called. Possible error codes are: GSOCK_INVSOCK if socket has not
269 * been initialized, GSOCK_INVADDR if the local address has not been
270 * defined and GSOCK_IOERR for other internal errors.
271 */
a324a7bc
GL
272GSocketError GSocket_SetServer(GSocket *sck)
273{
274 int type;
275
276 assert(sck != NULL);
277
278 if (sck->m_fd != -1) {
279 sck->m_error = GSOCK_INVSOCK;
280 return GSOCK_INVSOCK;
281 }
282
283 if (!sck->m_local) {
284 sck->m_error = GSOCK_INVADDR;
285 return GSOCK_INVADDR;
286 }
287
f61815af
GL
288 /* We always have a stream here */
289 sck->m_stream = TRUE;
8f7173ab 290 sck->m_server = TRUE;
a324a7bc 291
f61815af
GL
292 /* Create the socket */
293 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
a324a7bc
GL
294
295 if (sck->m_fd == -1) {
296 sck->m_error = GSOCK_IOERR;
297 return GSOCK_IOERR;
298 }
299
f61815af 300 /* Bind the socket to the LOCAL address */
a324a7bc
GL
301 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
302 close(sck->m_fd);
303 sck->m_fd = -1;
304 sck->m_error = GSOCK_IOERR;
305 return GSOCK_IOERR;
306 }
307
f61815af 308 /* Enable listening up to 5 connections */
a324a7bc
GL
309 if (listen(sck->m_fd, 5) < 0) {
310 close(sck->m_fd);
311 sck->m_fd = -1;
312 sck->m_error = GSOCK_IOERR;
313 return GSOCK_IOERR;
314 }
315
2f7c2af5 316 _GSocket_Configure_Callbacks(sck);
dc26b37a 317 GSocket_SetNonBlocking(sck, sck->m_non_blocking);
39b91eca
GL
318 GSocket_SetTimeout(sck, sck->m_timeout);
319
a324a7bc 320 return GSOCK_NOERROR;
a324a7bc
GL
321}
322
2f7c2af5
GRG
323/* GSocket_WaitConnection:
324 * Waits for an incoming client connection.
325 */
a324a7bc
GL
326GSocket *GSocket_WaitConnection(GSocket *socket)
327{
328 GSocket *connection;
329
330 assert(socket != NULL);
331
f61815af 332 /* If the socket has already been created, we exit immediately */
a324a7bc
GL
333 if (socket->m_fd == -1 || !socket->m_server) {
334 socket->m_error = GSOCK_INVSOCK;
335 return NULL;
336 }
337
f61815af 338 /* Reenable GSOCK_CONNECTION event */
a324a7bc
GL
339 _GSocket_Enable(socket, GSOCK_CONNECTION);
340
f61815af 341 /* Create a GSocket object for the new connection */
a324a7bc 342 connection = GSocket_new();
aa6d9706
GL
343 if (!connection) {
344 connection->m_error = GSOCK_MEMERR;
345 return NULL;
346 }
a324a7bc 347
f61815af 348 /* Accept the incoming connection */
aa6d9706 349 ENABLE_TIMEOUT(connection);
a324a7bc 350 connection->m_fd = accept(socket->m_fd, NULL, NULL);
aa6d9706 351 DISABLE_TIMEOUT(connection);
a324a7bc
GL
352 if (connection->m_fd == -1) {
353 GSocket_destroy(connection);
aa6d9706
GL
354 switch(errno) {
355 case EINTR:
356 case ETIMEDOUT:
357 connection->m_error = GSOCK_TIMEDOUT;
358 break;
359 case EWOULDBLOCK:
360 connection->m_error = GSOCK_WOULDBLOCK;
361 break;
362 default:
363 connection->m_error = GSOCK_IOERR;
364 break;
365 }
a324a7bc
GL
366 return NULL;
367 }
368
f61815af 369 /* Initialize all fields */
a324a7bc
GL
370 connection->m_stream = TRUE;
371 connection->m_server = FALSE;
372 connection->m_oriented = TRUE;
373
2f7c2af5
GRG
374 _GSocket_Configure_Callbacks(connection);
375 GSocket_SetNonBlocking(connection, connection->m_non_blocking);
376 GSocket_SetTimeout(connection, connection->m_timeout);
377
a324a7bc
GL
378 return connection;
379}
380
381/* Non oriented connections */
382
383GSocketError GSocket_SetNonOriented(GSocket *sck)
384{
385 assert(sck != NULL);
386
387 if (sck->m_fd != -1) {
388 sck->m_error = GSOCK_INVSOCK;
389 return GSOCK_INVSOCK;
390 }
391
392 if (!sck->m_local) {
393 sck->m_error = GSOCK_INVADDR;
394 return GSOCK_INVADDR;
395 }
396
397 sck->m_stream = FALSE;
398 sck->m_server = FALSE;
399 sck->m_oriented = FALSE;
400
f61815af 401 /* Create the socket */
a324a7bc
GL
402 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
403
aa6d9706
GL
404 if (sck->m_fd < 0) {
405 sck->m_error = GSOCK_IOERR;
406 return GSOCK_IOERR;
407 }
408
f61815af 409 /* Bind it to the LOCAL address */
a324a7bc
GL
410 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
411 close(sck->m_fd);
412 sck->m_fd = -1;
413 sck->m_error = GSOCK_IOERR;
414 return GSOCK_IOERR;
415 }
416
2f7c2af5 417 _GSocket_Configure_Callbacks(sck);
dc26b37a 418 GSocket_SetNonBlocking(sck, sck->m_non_blocking);
39b91eca
GL
419 GSocket_SetTimeout(sck, sck->m_timeout);
420
a324a7bc
GL
421 return GSOCK_NOERROR;
422}
423
424/* Client specific parts */
425
2f7c2af5
GRG
426/* GSocket_Connect:
427 * Establishes a client connection to a server using the "Peer"
428 * field of GSocket. "Peer" must be set by GSocket_SetPeer() before
429 * GSocket_Connect() is called. Possible error codes are GSOCK_INVSOCK,
430 * GSOCK_INVADDR, GSOCK_TIMEDOUT, GSOCK_WOULDBLOCK and GSOCK_IOERR.
431 * If a socket is nonblocking and Connect() returns GSOCK_WOULDBLOCK,
432 * the connection request can be completed later. Use GSocket_Select()
433 * to check or wait for a GSOCK_CONNECTION event.
434 */
a324a7bc
GL
435GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
436{
aa6d9706 437 int type, err;
a324a7bc
GL
438
439 assert(sck != NULL);
440
441 if (sck->m_fd != -1) {
442 sck->m_error = GSOCK_INVSOCK;
443 return GSOCK_INVSOCK;
444 }
445
446 if (!sck->m_peer) {
447 sck->m_error = GSOCK_INVADDR;
448 return GSOCK_INVADDR;
449 }
450
f61815af 451 /* Test whether we want the socket to be a stream (e.g. TCP) */
a324a7bc
GL
452 sck->m_stream = (stream == GSOCK_STREAMED);
453 sck->m_oriented = TRUE;
454
455 if (sck->m_stream)
456 type = SOCK_STREAM;
457 else
458 type = SOCK_DGRAM;
459
f61815af 460 /* Create the socket */
a324a7bc
GL
461 sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0);
462
463 if (sck->m_fd == -1) {
464 sck->m_error = GSOCK_IOERR;
465 return GSOCK_IOERR;
466 }
467
2f7c2af5 468 _GSocket_Configure_Callbacks(sck);
aa6d9706
GL
469 GSocket_SetNonBlocking(sck, sck->m_non_blocking);
470 GSocket_SetTimeout(sck, sck->m_timeout);
471
f61815af 472 /* Connect it to the PEER address */
aa6d9706
GL
473 ENABLE_TIMEOUT(sck);
474 err = connect(sck->m_fd, sck->m_peer->m_addr, sck->m_peer->m_len);
475 DISABLE_TIMEOUT(sck);
476
477 if (err != 0 && errno != EINPROGRESS) {
a324a7bc
GL
478 close(sck->m_fd);
479 sck->m_fd = -1;
aa6d9706
GL
480 switch (errno) {
481 case EINTR:
482 case ETIMEDOUT:
483 sck->m_error = GSOCK_TIMEDOUT;
484 break;
485 default:
486 sck->m_error = GSOCK_IOERR;
487 break;
488 }
a324a7bc
GL
489 return GSOCK_IOERR;
490 }
491
f61815af 492 /* It is not a server */
aa6d9706
GL
493 sck->m_server = FALSE;
494 sck->m_establishing = (errno == EINPROGRESS);
39b91eca 495
aa6d9706 496 return (sck->m_establishing) ? GSOCK_WOULDBLOCK : GSOCK_NOERROR;
a324a7bc
GL
497}
498
499/* Generic IO */
500
501/* Like recv(), send(), ... */
502int GSocket_Read(GSocket *socket, char *buffer, int size)
503{
504 assert(socket != NULL);
505
506 if (socket->m_fd == -1 || socket->m_server) {
507 socket->m_error = GSOCK_INVSOCK;
508 return -1;
509 }
510
f61815af 511 /* Reenable GSOCK_INPUT event */
a324a7bc
GL
512 _GSocket_Enable(socket, GSOCK_INPUT);
513
f61815af 514 if (socket->m_stream)
a324a7bc
GL
515 return _GSocket_Recv_Stream(socket, buffer, size);
516 else
517 return _GSocket_Recv_Dgram(socket, buffer, size);
518}
519
520int GSocket_Write(GSocket *socket, const char *buffer,
521 int size)
522{
523 assert(socket != NULL);
524
525 if (socket->m_fd == -1 || socket->m_server) {
526 socket->m_error = GSOCK_INVSOCK;
527 return -1;
528 }
529
530 _GSocket_Enable(socket, GSOCK_OUTPUT);
531
f61815af 532 if (socket->m_stream)
a324a7bc
GL
533 return _GSocket_Send_Stream(socket, buffer, size);
534 else
535 return _GSocket_Send_Dgram(socket, buffer, size);
536}
537
ef25e638
GRG
538/* GSocket_Select:
539 * Polls the socket to determine its status. This function will
540 * check for the events specified in the 'flags' parameter, and
541 * it will return a mask indicating which operations can be
542 * performed. This function won't block, regardless of the
543 * mode (blocking|nonblocking) of the socket.
544 */
545GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
a324a7bc 546{
ef25e638 547 fd_set readfds, writefds, exceptfds;
a324a7bc 548 struct timeval tv;
ef25e638
GRG
549 GSocketEventFlags mask;
550 int error, len;
a324a7bc
GL
551
552 assert(socket != NULL);
553
ef25e638
GRG
554 if (socket->m_fd == -1)
555 {
a324a7bc
GL
556 socket->m_error = GSOCK_INVSOCK;
557 return FALSE;
558 }
559
ef25e638
GRG
560 FD_ZERO(&readfds);
561 FD_ZERO(&writefds);
562 FD_ZERO(&exceptfds);
563 FD_SET(socket->m_fd, &readfds);
564 FD_SET(socket->m_fd, &writefds);
565 FD_SET(socket->m_fd, &exceptfds);
a324a7bc
GL
566
567 tv.tv_sec = 0;
568 tv.tv_usec = 0;
ef25e638
GRG
569 select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv);
570
571 mask = 0;
572
573 /* If select() says that the socket is readable, then we have
574 * no way to distinguish if that means 'data available' (to
575 * recv) or 'incoming connection' (to accept). The same goes
576 * for writability: we cannot distinguish between 'you can
577 * send data' and 'connection request completed'. So we will
578 * assume the following: if the flag was set upon entry,
579 * that means that the event was possible.
580 */
581 if (FD_ISSET(socket->m_fd, &readfds))
582 {
583 mask |= (flags & GSOCK_CONNECTION_FLAG);
584 mask |= (flags & GSOCK_INPUT_FLAG);
585 }
586 if (FD_ISSET(socket->m_fd, &writefds))
587 {
588 if (socket->m_establishing)
589 {
590 getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, &error, &len);
591
592 if (error)
593 mask |= (flags & GSOCK_LOST_FLAG);
594 else
595 mask |= (flags & GSOCK_CONNECTION_FLAG);
596 }
597 mask |= (flags & GSOCK_OUTPUT_FLAG);
598 }
599 if (FD_ISSET(socket->m_fd, &exceptfds))
600 mask |= (flags & GSOCK_LOST_FLAG);
a324a7bc 601
ef25e638 602 return mask;
a324a7bc
GL
603}
604
605/* Flags */
606
2f7c2af5
GRG
607/* GSocket_SetNonBlocking:
608 * Sets the socket to non-blocking mode. This is useful if
609 * we don't want to wait.
610 */
54e575f9 611void GSocket_SetNonBlocking(GSocket *socket, bool non_block)
a324a7bc
GL
612{
613 assert(socket != NULL);
614
dc26b37a 615 socket->m_non_blocking = non_block;
a324a7bc
GL
616
617 if (socket->m_fd != -1)
54e575f9 618 ioctl(socket->m_fd, FIONBIO, &non_block);
a324a7bc
GL
619}
620
2f7c2af5
GRG
621/* GSocket_SetTimeout:
622 * Sets the timeout for blocking calls. Time is
623 * expressed in milliseconds.
39b91eca
GL
624 */
625void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
626{
627 assert(socket != NULL);
628
54e575f9 629 socket->m_timeout = millisec;
39b91eca
GL
630}
631
2f7c2af5
GRG
632/* GSocket_GetError:
633 * Returns the last error occured for this socket.
634 */
a324a7bc
GL
635GSocketError GSocket_GetError(GSocket *socket)
636{
637 assert(socket != NULL);
638
639 return socket->m_error;
640}
641
642/* Callbacks */
643
2f7c2af5
GRG
644/* Only one callback is possible for each event (INPUT, OUTPUT, CONNECTION
645 * and LOST). The callbacks are called in the following situations:
646 *
647 * INPUT: There is at least one byte in the input buffer
648 * OUTPUT: The system is sure that the next write call will not block
649 * CONNECTION: Two cases are possible:
650 * Client socket -> the connection is established
651 * Server socket -> a client requests a connection
652 * LOST: The connection is lost
653 *
654 * An event is generated only once and its state is reseted when the
655 * relative IO call is requested.
656 * For example: INPUT -> GSocket_Read()
657 * CONNECTION -> GSocket_Accept()
658 */
659
660/* GSocket_SetCallback:
661 * Enables the callbacks specified by 'flags'. Note that 'flags'
662 * may be a combination of flags OR'ed toghether, so the same
663 * callback function can be made to accept different events.
664 * The callback function must have the following prototype:
665 *
666 * void function(GSocket *socket, GSocketEvent event, char *cdata)
667 */
ef25e638 668void GSocket_SetCallback(GSocket *socket, GSocketEventFlags flags,
98781fa3 669 GSocketCallback callback, char *cdata)
a324a7bc
GL
670{
671 int count;
672
673 assert (socket != NULL);
674
675 for (count=0;count<GSOCK_MAX_EVENT;count++) {
f61815af
GL
676 /* We test each flag and, if it is enabled, we enable the corresponding
677 event */
ef25e638 678 if ((flags & (1 << count)) != 0) {
98781fa3 679 socket->m_cbacks[count] = callback;
a324a7bc 680 socket->m_data[count] = cdata;
a324a7bc
GL
681 }
682 }
2f7c2af5 683 _GSocket_Configure_Callbacks(socket);
a324a7bc
GL
684}
685
2f7c2af5
GRG
686/* GSocket_UnsetCallback:
687 * Disables all callbacks specified by 'flags', which may be a
688 * combination of flags OR'ed toghether.
689 */
ef25e638 690void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags flags)
a324a7bc 691{
2f7c2af5 692 int count;
a324a7bc
GL
693
694 assert(socket != NULL);
695
696 for (count=0;count<GSOCK_MAX_EVENT;count++) {
ef25e638 697 if ((flags & (1 << count)) != 0) {
98781fa3 698 socket->m_cbacks[count] = NULL;
a324a7bc
GL
699 }
700 }
2f7c2af5 701 _GSocket_Configure_Callbacks(socket);
a324a7bc
GL
702}
703
2f7c2af5
GRG
704#define CALL_CALLBACK(socket, event) \
705if (socket->m_iocalls[event] && socket->m_cbacks[event]) { \
706 _GSocket_Disable(socket, event); \
707 socket->m_cbacks[event](socket, event, socket->m_data[event]); \
a324a7bc
GL
708}
709
a324a7bc
GL
710void _GSocket_Enable(GSocket *socket, GSocketEvent event)
711{
712 socket->m_iocalls[event] = TRUE;
98781fa3 713 if (socket->m_cbacks[event])
39b91eca 714 _GSocket_Install_Callback(socket, event);
a324a7bc
GL
715}
716
717void _GSocket_Disable(GSocket *socket, GSocketEvent event)
718{
719 socket->m_iocalls[event] = FALSE;
98781fa3 720 if (socket->m_cbacks[event])
39b91eca 721 _GSocket_Uninstall_Callback(socket, event);
a324a7bc
GL
722}
723
2f7c2af5
GRG
724void _GSocket_Configure_Callbacks(GSocket *socket)
725{
726 int count;
727 for (count=0;count<GSOCK_MAX_EVENT;count++) {
728 if ((socket->m_cbacks[count]) != NULL) {
90bb2919 729 _GSocket_Enable(socket, count);
2f7c2af5 730 } else {
90bb2919 731 _GSocket_Disable(socket, count);
2f7c2af5
GRG
732 }
733 }
734}
735
a324a7bc
GL
736int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
737{
738 int ret;
739
740 MASK_SIGNAL();
54e575f9 741 ENABLE_TIMEOUT(socket);
a324a7bc 742 ret = recv(socket->m_fd, buffer, size, 0);
54e575f9 743 DISABLE_TIMEOUT(socket);
a324a7bc 744 UNMASK_SIGNAL();
54e575f9 745
aa6d9706
GL
746 if (ret == -1 &&
747 errno != ETIMEDOUT && errno != EWOULDBLOCK && errno != EINTR) {
748 socket->m_error = GSOCK_IOERR;
749 return -1;
a324a7bc 750 }
8f7173ab 751 if (errno == EWOULDBLOCK) {
98781fa3 752 socket->m_error = GSOCK_WOULDBLOCK;
9592b687
GL
753 return -1;
754 }
aa6d9706
GL
755 if (errno == ETIMEDOUT || errno == EINTR) {
756 socket->m_error = GSOCK_TIMEDOUT;
757 return -1;
758 }
a324a7bc
GL
759 return ret;
760}
761
762int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
763{
764 struct sockaddr from;
ca17eff3
RR
765 SOCKLEN_T fromlen;
766 int ret;
aa6d9706 767 GSocketError err;
a324a7bc
GL
768
769 fromlen = sizeof(from);
770
771 MASK_SIGNAL();
54e575f9 772 ENABLE_TIMEOUT(socket);
a324a7bc 773 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen);
54e575f9 774 DISABLE_TIMEOUT(socket);
a324a7bc 775 UNMASK_SIGNAL();
aa6d9706 776 if (ret == -1 && errno != EWOULDBLOCK && errno != EINTR && errno != ETIMEDOUT) {
a324a7bc
GL
777 socket->m_error = GSOCK_IOERR;
778 return -1;
779 }
8f7173ab 780 if (errno == EWOULDBLOCK) {
98781fa3 781 socket->m_error = GSOCK_WOULDBLOCK;
9592b687
GL
782 return -1;
783 }
aa6d9706
GL
784 if (errno == ETIMEDOUT || errno == EINTR) {
785 socket->m_error = GSOCK_TIMEDOUT;
786 return -1;
787 }
a324a7bc 788
f61815af 789 /* Translate a system address into a GSocket address */
e00f35bb 790 if (!socket->m_peer) {
a324a7bc 791 socket->m_peer = GAddress_new();
e00f35bb
GL
792 if (!socket->m_peer) {
793 socket->m_error = GSOCK_MEMERR;
794 return -1;
795 }
796 }
aa6d9706
GL
797 err = _GAddress_translate_from(socket->m_peer, &from, fromlen);
798 if (err != GSOCK_NOERROR) {
799 GAddress_destroy(socket->m_peer);
800 socket->m_peer = NULL;
801 socket->m_error = err;
e00f35bb 802 return -1;
aa6d9706 803 }
a324a7bc
GL
804
805 return ret;
806}
807
808int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
809{
810 int ret;
aa6d9706 811 GSocketError err;
a324a7bc
GL
812
813 MASK_SIGNAL();
54e575f9 814 ENABLE_TIMEOUT(socket);
a324a7bc 815 ret = send(socket->m_fd, buffer, size, 0);
54e575f9 816 DISABLE_TIMEOUT(socket);
a324a7bc 817 UNMASK_SIGNAL();
aa6d9706 818 if (ret == -1 && errno != EWOULDBLOCK && errno != ETIMEDOUT && errno != EINTR) {
a324a7bc
GL
819 socket->m_error = GSOCK_IOERR;
820 return -1;
821 }
8f7173ab 822 if (errno == EWOULDBLOCK) {
98781fa3 823 socket->m_error = GSOCK_WOULDBLOCK;
9592b687
GL
824 return -1;
825 }
aa6d9706
GL
826 if (errno == ETIMEDOUT || errno == EINTR) {
827 socket->m_error = GSOCK_TIMEDOUT;
828 return -1;
829 }
a324a7bc
GL
830 return ret;
831}
832
833int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
834{
835 struct sockaddr *addr;
836 int len, ret;
aa6d9706 837 GSocketError err;
a324a7bc
GL
838
839 if (!socket->m_peer) {
840 socket->m_error = GSOCK_INVADDR;
841 return -1;
842 }
843
aa6d9706
GL
844 err = _GAddress_translate_to(socket->m_peer, &addr, &len);
845 if (err != GSOCK_NOERROR) {
846 socket->m_error = err;
e00f35bb
GL
847 return -1;
848 }
a324a7bc
GL
849
850 MASK_SIGNAL();
54e575f9 851 ENABLE_TIMEOUT(socket);
a324a7bc 852 ret = sendto(socket->m_fd, buffer, size, 0, addr, len);
54e575f9 853 DISABLE_TIMEOUT(socket);
a324a7bc 854 UNMASK_SIGNAL();
a324a7bc 855
f61815af 856 /* Frees memory allocated from _GAddress_translate_to */
a324a7bc
GL
857 free(addr);
858
8f7173ab 859 if (ret == -1 && errno != EWOULDBLOCK) {
9592b687
GL
860 socket->m_error = GSOCK_IOERR;
861 return -1;
862 }
8f7173ab 863 if (errno == EWOULDBLOCK) {
98781fa3 864 socket->m_error = GSOCK_WOULDBLOCK;
9592b687
GL
865 return -1;
866 }
867
a324a7bc
GL
868 return ret;
869}
870
871void _GSocket_Detected_Read(GSocket *socket)
872{
873 char c;
874 int ret;
875
876 if (socket->m_stream) {
877 ret = recv(socket->m_fd, &c, 1, MSG_PEEK);
878
879 if (ret < 0 && socket->m_server) {
aa6d9706 880 CALL_CALLBACK(socket, GSOCK_CONNECTION);
a324a7bc
GL
881 return;
882 }
883
884 if (ret > 0) {
aa6d9706 885 CALL_CALLBACK(socket, GSOCK_INPUT);
a324a7bc 886 } else {
aa6d9706 887 CALL_CALLBACK(socket, GSOCK_LOST);
a324a7bc
GL
888 }
889 }
890}
891
892void _GSocket_Detected_Write(GSocket *socket)
893{
aa6d9706
GL
894 if (socket->m_establishing) {
895 int error, len;
896
897 len = sizeof(error);
a324a7bc 898
aa6d9706
GL
899 socket->m_establishing = FALSE;
900 getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, &error, &len);
901
902 if (error) {
903 socket->m_error = GSOCK_IOERR;
904 GSocket_Shutdown(socket);
905 } else
906 socket->m_error = GSOCK_NOERROR;
907
908 CALL_CALLBACK(socket, GSOCK_CONNECTION);
909 } else
910 CALL_CALLBACK(socket, GSOCK_OUTPUT);
911}
a324a7bc
GL
912
913/*
914 * -------------------------------------------------------------------------
915 * GAddress
916 * -------------------------------------------------------------------------
917 */
918
f61815af
GL
919/* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY or
920 * GSOCK_*family*. In case it is GSOCK_NOFAMILY, it initializes address to be
921 * a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR.
922 */
a324a7bc
GL
923#define CHECK_ADDRESS(address, family, retval) \
924{ \
925 if (address->m_family == GSOCK_NOFAMILY) \
54e575f9
GL
926 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) {\
927 return address->m_error; \
e00f35bb 928 }\
a324a7bc
GL
929 if (address->m_family != GSOCK_##family) {\
930 address->m_error = GSOCK_INVADDR; \
931 return retval; \
932 } \
933}
934
935GAddress *GAddress_new()
936{
937 GAddress *address;
938
939 address = (GAddress *)malloc(sizeof(GAddress));
940
e00f35bb
GL
941 if (address == NULL)
942 return NULL;
943
a324a7bc
GL
944 address->m_family = GSOCK_NOFAMILY;
945 address->m_addr = NULL;
946 address->m_len = 0;
947
948 return address;
949}
950
951GAddress *GAddress_copy(GAddress *address)
952{
953 GAddress *addr2;
954
955 assert(address != NULL);
956
957 addr2 = (GAddress *)malloc(sizeof(GAddress));
e00f35bb
GL
958
959 if (addr2 == NULL)
960 return NULL;
961
a324a7bc
GL
962 memcpy(addr2, address, sizeof(GAddress));
963
964 if (address->m_addr) {
965 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
e00f35bb
GL
966 if (addr2->m_addr == NULL) {
967 free(addr2);
968 return NULL;
969 }
a324a7bc
GL
970 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
971 }
972
973 return addr2;
974}
975
976void GAddress_destroy(GAddress *address)
977{
978 assert(address != NULL);
979
980 free(address);
981}
982
983void GAddress_SetFamily(GAddress *address, GAddressType type)
984{
985 assert(address != NULL);
986
987 address->m_family = type;
988}
989
990GAddressType GAddress_GetFamily(GAddress *address)
991{
992 assert(address != NULL);
993
994 return address->m_family;
995}
996
54e575f9 997GSocketError _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){
a324a7bc
GL
998 address->m_realfamily = addr->sa_family;
999 switch (addr->sa_family) {
1000 case AF_INET:
1001 address->m_family = GSOCK_INET;
1002 break;
1003 case AF_UNIX:
1004 address->m_family = GSOCK_UNIX;
1005 break;
efee48a0 1006#ifdef AF_INET6
a324a7bc
GL
1007 case AF_INET6:
1008 address->m_family = GSOCK_INET6;
1009 break;
efee48a0 1010#endif
a324a7bc 1011 default:
ca17eff3 1012 {
54e575f9
GL
1013 address->m_error = GSOCK_INVOP;
1014 return GSOCK_INVOP;
ca17eff3 1015 }
a324a7bc
GL
1016 }
1017
1018 if (address->m_addr)
1019 free(address->m_addr);
1020
1021 address->m_len = len;
1022 address->m_addr = (struct sockaddr *)malloc(len);
54e575f9
GL
1023 if (address->m_addr == NULL) {
1024 address->m_error = GSOCK_MEMERR;
1025 return GSOCK_MEMERR;
1026 }
a324a7bc 1027 memcpy(address->m_addr, addr, len);
e00f35bb 1028
54e575f9 1029 return GSOCK_NOERROR;
a324a7bc
GL
1030}
1031
54e575f9
GL
1032GSocketError _GAddress_translate_to(GAddress *address,
1033 struct sockaddr **addr, int *len)
a324a7bc
GL
1034{
1035 if (!address->m_addr) {
54e575f9
GL
1036 address->m_error = GSOCK_INVADDR;
1037 return GSOCK_INVADDR;
a324a7bc
GL
1038 }
1039
1040 *len = address->m_len;
1041 *addr = (struct sockaddr *)malloc(address->m_len);
54e575f9
GL
1042 if (*addr == NULL) {
1043 address->m_error = GSOCK_MEMERR;
1044 return GSOCK_MEMERR;
1045 }
e00f35bb 1046
a324a7bc 1047 memcpy(*addr, address->m_addr, address->m_len);
54e575f9 1048 return GSOCK_NOERROR;
a324a7bc
GL
1049}
1050
1051/*
1052 * -------------------------------------------------------------------------
1053 * Internet address family
1054 * -------------------------------------------------------------------------
1055 */
1056
54e575f9 1057GSocketError _GAddress_Init_INET(GAddress *address)
a324a7bc 1058{
e00f35bb 1059 address->m_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
54e575f9
GL
1060 if (address->m_addr == NULL) {
1061 address->m_error = GSOCK_MEMERR;
1062 return GSOCK_MEMERR;
1063 }
e00f35bb 1064
a324a7bc 1065 address->m_len = sizeof(struct sockaddr_in);
e00f35bb 1066
a324a7bc
GL
1067 address->m_family = GSOCK_INET;
1068 address->m_realfamily = PF_INET;
1069 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
1070 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
e00f35bb 1071
cc345f78 1072 return GSOCK_NOERROR;
a324a7bc
GL
1073}
1074
1075GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
1076{
1077 struct hostent *he;
1078 struct in_addr *addr;
1079
1080 assert(address != NULL);
1081
1082 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1083
1084 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1085
f61815af 1086 /* If it is a numeric host name, convert it now */
d5b08e7b 1087#if defined(HAVE_INET_ATON)
a324a7bc 1088 if (inet_aton(hostname, addr) == 0) {
d5b08e7b 1089#elif defined(HAVE_INET_ADDR)
e96ac54e
GL
1090 /* Fix from Guillermo Rodriguez Garcia <guille@iies.es> */
1091 if ( (addr->s_addr = inet_addr(hostname)) == -1 ) {
1092#else
1093 /* Use gethostbyname by default */
1094 if (1) {
1095#endif
a324a7bc
GL
1096 struct in_addr *array_addr;
1097
f61815af 1098 /* It is a real name, we solve it */
a324a7bc
GL
1099 if ((he = gethostbyname(hostname)) == NULL) {
1100 address->m_error = GSOCK_NOHOST;
1101 return GSOCK_NOHOST;
1102 }
1103 array_addr = (struct in_addr *) *(he->h_addr_list);
1104 addr->s_addr = array_addr[0].s_addr;
1105 }
1106 return GSOCK_NOERROR;
1107}
1108
1109GSocketError GAddress_INET_SetHostAddress(GAddress *address,
1110 unsigned long hostaddr)
1111{
1112 struct in_addr *addr;
1113
1114 assert(address != NULL);
1115
1116 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1117
1118 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1119 addr->s_addr = hostaddr;
1120
1121 return GSOCK_NOERROR;
1122}
1123
5a96d2f4
GL
1124GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1125 const char *protocol)
a324a7bc
GL
1126{
1127 struct servent *se;
1128 struct sockaddr_in *addr;
1129
1130 assert(address != NULL);
1131 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1132
1133 if (!port) {
1134 address->m_error = GSOCK_INVPORT;
54e575f9 1135 return GSOCK_INVPORT;
a324a7bc
GL
1136 }
1137
5a96d2f4 1138 se = getservbyname(port, protocol);
a324a7bc
GL
1139 if (!se) {
1140 if (isdigit(port[0])) {
1141 int port_int;
1142
1143 port_int = atoi(port);
1144 addr = (struct sockaddr_in *)address->m_addr;
1145 addr->sin_port = htons(port_int);
1146 return GSOCK_NOERROR;
1147 }
1148
1149 address->m_error = GSOCK_INVPORT;
1150 return GSOCK_INVPORT;
1151 }
1152
1153 addr = (struct sockaddr_in *)address->m_addr;
1154 addr->sin_port = se->s_port;
1155
1156 return GSOCK_NOERROR;
1157}
1158
1159GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1160{
1161 struct sockaddr_in *addr;
1162
1163 assert(address != NULL);
1164 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1165
1166 addr = (struct sockaddr_in *)address->m_addr;
1167 addr->sin_port = htons(port);
1168
1169 return GSOCK_NOERROR;
1170}
1171
1172GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1173{
1174 struct hostent *he;
1175 char *addr_buf;
1176 struct sockaddr_in *addr;
1177
1178 assert(address != NULL);
1179 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
1180
1181 addr = (struct sockaddr_in *)address->m_addr;
1182 addr_buf = (char *)&(addr->sin_addr);
1183
1184 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
1185 if (he == NULL) {
1186 address->m_error = GSOCK_NOHOST;
1187 return GSOCK_NOHOST;
1188 }
1189
1190 strncpy(hostname, he->h_name, sbuf);
1191
1192 return GSOCK_NOERROR;
1193}
1194
1195unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1196{
1197 struct sockaddr_in *addr;
1198
1199 assert(address != NULL);
1200 CHECK_ADDRESS(address, INET, 0);
1201
1202 addr = (struct sockaddr_in *)address->m_addr;
1203
1204 return addr->sin_addr.s_addr;
1205}
1206
1207unsigned short GAddress_INET_GetPort(GAddress *address)
1208{
1209 struct sockaddr_in *addr;
1210
1211 assert(address != NULL);
1212 CHECK_ADDRESS(address, INET, 0);
1213
1214 addr = (struct sockaddr_in *)address->m_addr;
1215 return ntohs(addr->sin_port);
1216}
1217
1218/*
1219 * -------------------------------------------------------------------------
1220 * Unix address family
1221 * -------------------------------------------------------------------------
1222 */
1223
54e575f9 1224GSocketError _GAddress_Init_UNIX(GAddress *address)
a324a7bc 1225{
a324a7bc 1226 address->m_addr = (struct sockaddr *)malloc(address->m_len);
54e575f9
GL
1227 if (address->m_addr == NULL) {
1228 address->m_error = GSOCK_MEMERR;
1229 return GSOCK_MEMERR;
1230 }
e00f35bb
GL
1231
1232 address->m_len = sizeof(struct sockaddr_un);
a324a7bc
GL
1233 address->m_family = GSOCK_UNIX;
1234 address->m_realfamily = PF_UNIX;
1235 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
1236 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
e00f35bb
GL
1237
1238 return TRUE;
a324a7bc
GL
1239}
1240
1241GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1242{
1243 struct sockaddr_un *addr;
1244
1245 assert(address != NULL);
1246
1247 CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR);
1248
1249 addr = ((struct sockaddr_un *)address->m_addr);
1250 memcpy(addr->sun_path, path, strlen(path));
1251
1252 return GSOCK_NOERROR;
1253}
1254
1255GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1256{
1257 struct sockaddr_un *addr;
1258
1259 assert(address != NULL);
1260 CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR);
1261
1262 addr = (struct sockaddr_un *)address->m_addr;
1263
1264 strncpy(path, addr->sun_path, sbuf);
1265
1266 return GSOCK_NOERROR;
1267}
813c20a6 1268
d422d01e
RR
1269#endif
1270 /* wxUSE_SOCKETS */