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