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