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