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