]> git.saurik.com Git - wxWidgets.git/blob - src/unix/gsocket.c
Did somework on the generic dialogs,
[wxWidgets.git] / src / unix / gsocket.c
1 /* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsocket.c
4 * Purpose: GSocket main Unix file
5 * CVSID: $Id$
6 * -------------------------------------------------------------------------
7 */
8
9 #include "wx/setup.h"
10
11 #if wxUSE_SOCKETS
12
13 #include <assert.h>
14 #include <sys/ioctl.h>
15 #include <sys/types.h>
16 #ifdef vms
17 #include <socket.h>
18 #else
19 #include <sys/socket.h>
20 #endif
21 #include <sys/un.h>
22 #include <sys/time.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <netdb.h>
26 #include <errno.h>
27
28 #include <string.h>
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <ctype.h>
34
35 #ifdef sun
36 # include <sys/filio.h>
37 #endif
38
39 #ifdef sgi
40 # include <bstring.h>
41 #endif
42
43 #include <signal.h>
44
45 #include "wx/gsocket.h"
46 #include "gsockunx.h"
47
48 #ifndef SOCKLEN_T
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
58 #endif
59
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
68 /* Global initialisers */
69
70 bool GSocket_Init()
71 {
72 return TRUE;
73 }
74
75 void GSocket_Cleanup()
76 {
77 }
78
79 /* Constructors / Destructors */
80
81 GSocket *GSocket_new()
82 {
83 int i;
84 GSocket *socket;
85
86 socket = (GSocket *)malloc(sizeof(GSocket));
87
88 if (socket == NULL)
89 return NULL;
90
91 socket->m_fd = -1;
92 for (i=0;i<GSOCK_MAX_EVENT;i++) {
93 socket->m_cbacks[i] = NULL;
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;
102 socket->m_non_blocking = FALSE;
103 socket->m_timeout = 10*60*1000;
104 /* 10 minutes * 60 sec * 1000 millisec */
105
106 /* We initialize the GUI specific entries here */
107 _GSocket_GUI_Init(socket);
108
109 return socket;
110 }
111
112 void GSocket_destroy(GSocket *socket)
113 {
114 assert(socket != NULL);
115
116 /* First, we check that the socket is really shutdowned */
117 if (socket->m_fd != -1)
118 GSocket_Shutdown(socket);
119
120 /* We destroy GUI specific variables */
121 _GSocket_GUI_Destroy(socket);
122
123 /* We destroy private addresses */
124 if (socket->m_local)
125 GAddress_destroy(socket->m_local);
126
127 if (socket->m_peer)
128 GAddress_destroy(socket->m_peer);
129
130 /* We destroy socket itself */
131 free(socket);
132 }
133
134 void GSocket_Shutdown(GSocket *socket)
135 {
136 int evt;
137
138 assert(socket != NULL);
139
140 /* If socket has been created, we shutdown it */
141 if (socket->m_fd != -1) {
142 /* Only oriented connection should be shutdowned */
143 if (socket->m_oriented)
144 shutdown(socket->m_fd, 2);
145 close(socket->m_fd);
146 socket->m_fd = -1;
147 }
148
149 /* We also disable GUI callbacks */
150 for (evt=0;evt<GSOCK_MAX_EVENT;evt++)
151 _GSocket_Uninstall_Callback(socket, evt);
152 }
153
154 /* Address handling */
155
156 GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
157 {
158 assert(socket != NULL);
159
160 if ((socket->m_fd != -1 && !socket->m_server)) {
161 socket->m_error = GSOCK_INVSOCK;
162 return GSOCK_INVSOCK;
163 }
164
165 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
166 socket->m_error = GSOCK_INVADDR;
167 return GSOCK_INVADDR;
168 }
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
178 GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
179 {
180 assert(socket != NULL);
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
195 GAddress *GSocket_GetLocal(GSocket *socket)
196 {
197 GAddress *address;
198 struct sockaddr addr;
199 SOCKLEN_T size;
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();
219 if (address == NULL) {
220 socket->m_error = GSOCK_MEMERR;
221 return NULL;
222 }
223 if (_GAddress_translate_from(address, &addr, size) != GSOCK_NOERROR) {
224 GAddress_destroy(address);
225 return NULL;
226 }
227
228 return address;
229 }
230
231 GAddress *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.
247 In case, you haven't yet defined the local address, it returns GSOCK_INVADDR.
248 In the other cases it returns GSOCK_IOERR.
249 */
250 GSocketError 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
266 /* We always have a stream here */
267 sck->m_stream = TRUE;
268 sck->m_server = TRUE;
269
270 /* Create the socket */
271 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_STREAM, 0);
272
273 if (sck->m_fd == -1) {
274 sck->m_error = GSOCK_IOERR;
275 return GSOCK_IOERR;
276 }
277
278 /* Bind the socket to the LOCAL address */
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
286 /* Enable listening up to 5 connections */
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
294 GSocket_SetNonBlocking(sck, sck->m_non_blocking);
295 GSocket_SetTimeout(sck, sck->m_timeout);
296
297 return GSOCK_NOERROR;
298 }
299
300 /*
301 GSocket_WaitConnection() waits for an incoming client connection.
302 */
303 GSocket *GSocket_WaitConnection(GSocket *socket)
304 {
305 GSocket *connection;
306
307 assert(socket != NULL);
308
309 /* If the socket has already been created, we exit immediately */
310 if (socket->m_fd == -1 || !socket->m_server) {
311 socket->m_error = GSOCK_INVSOCK;
312 return NULL;
313 }
314
315 /* Reenable GSOCK_CONNECTION event */
316 _GSocket_Enable(socket, GSOCK_CONNECTION);
317
318 /* Create a GSocket object for the new connection */
319 connection = GSocket_new();
320
321 /* Accept the incoming connection */
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
329 /* Initialize all fields */
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
339 GSocketError 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
357 /* Create the socket */
358 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
359
360 /* Bind it to the LOCAL address */
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
368 GSocket_SetNonBlocking(sck, sck->m_non_blocking);
369 GSocket_SetTimeout(sck, sck->m_timeout);
370
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 */
381 GSocketError 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
397 /* Test whether we want the socket to be a stream (e.g. TCP) */
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
406 /* Create the socket */
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
414 /* Connect it to the PEER address */
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
423 /* It is not a server */
424 sck->m_server = FALSE;
425
426 GSocket_SetNonBlocking(sck, sck->m_non_blocking);
427 GSocket_SetTimeout(sck, sck->m_timeout);
428
429 return GSOCK_NOERROR;
430 }
431
432 /* Generic IO */
433
434 /* Like recv(), send(), ... */
435 int 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
444 /* Reenable GSOCK_INPUT event */
445 _GSocket_Enable(socket, GSOCK_INPUT);
446
447 if (socket->m_stream)
448 return _GSocket_Recv_Stream(socket, buffer, size);
449 else
450 return _GSocket_Recv_Dgram(socket, buffer, size);
451 }
452
453 int 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
465 if (socket->m_stream)
466 return _GSocket_Send_Stream(socket, buffer, size);
467 else
468 return _GSocket_Send_Dgram(socket, buffer, size);
469 }
470
471 bool 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 /*
497 GSocket_SetNonBlocking() puts the socket in non-blocking mode. This is useful
498 if we don't want to wait.
499 */
500 void GSocket_SetNonBlocking(GSocket *socket, bool non_block)
501 {
502 assert(socket != NULL);
503
504 socket->m_non_blocking = non_block;
505
506 if (socket->m_fd != -1)
507 ioctl(socket->m_fd, FIONBIO, &non_block);
508 }
509
510 /*
511 * GSocket_SetTimeout()
512 */
513
514 void GSocket_SetTimeout(GSocket *socket, unsigned long millisec)
515 {
516 assert(socket != NULL);
517
518 socket->m_timeout = millisec;
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. */
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
527 #ifdef CAN_USE_TIMEOUT
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 }
536 #endif
537 #endif
538 }
539
540 /*
541 GSocket_GetError() returns the last error occured on the socket stream.
542 */
543
544 GSocketError GSocket_GetError(GSocket *socket)
545 {
546 assert(socket != NULL);
547
548 return socket->m_error;
549 }
550
551 /* Callbacks */
552
553 /*
554 Only one callback is possible for each event (INPUT, OUTPUT, CONNECTION)
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
564 SetCallback accepts a combination of these flags so a same callback can
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 */
572 void GSocket_SetCallback(GSocket *socket, GSocketEventFlags event,
573 GSocketCallback callback, char *cdata)
574 {
575 int count;
576
577 assert (socket != NULL);
578
579 for (count=0;count<GSOCK_MAX_EVENT;count++) {
580 /* We test each flag and, if it is enabled, we enable the corresponding
581 event */
582 if ((event & (1 << count)) != 0) {
583 socket->m_cbacks[count] = callback;
584 socket->m_data[count] = cdata;
585 _GSocket_Enable(socket, count);
586 }
587 }
588 }
589
590 /*
591 UnsetCallback will disables all callbacks specified by "event".
592 NOTE: event may be a combination of flags
593 */
594 void GSocket_UnsetCallback(GSocket *socket, GSocketEventFlags event)
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);
603 socket->m_cbacks[count] = NULL;
604 }
605 }
606 }
607
608 #define CALL_FALLBACK(socket, event) \
609 if (socket->m_iocalls[event] && \
610 socket->m_cbacks[event]) {\
611 _GSocket_Disable(socket, event); \
612 socket->m_cbacks[event](socket, event, \
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
626 #define ENABLE_TIMEOUT(socket) \
627 { \
628 struct itimerval old_ival, new_ival; \
629 void (*old_timer_sig)(int); \
630 \
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);
638
639 #define DISABLE_TIMEOUT(socket) \
640 signal(SIGALRM, old_timer_sig); \
641 siginterrupt(SIGALRM, 0); \
642 setitimer(ITIMER_REAL, &old_ival, NULL); \
643 }
644
645 void _GSocket_Enable(GSocket *socket, GSocketEvent event)
646 {
647 socket->m_iocalls[event] = TRUE;
648 if (socket->m_cbacks[event])
649 _GSocket_Install_Callback(socket, event);
650 }
651
652 void _GSocket_Disable(GSocket *socket, GSocketEvent event)
653 {
654 socket->m_iocalls[event] = FALSE;
655 if (socket->m_cbacks[event])
656 _GSocket_Uninstall_Callback(socket, event);
657 }
658
659 int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
660 {
661 int ret;
662
663 MASK_SIGNAL();
664 ENABLE_TIMEOUT(socket);
665 ret = recv(socket->m_fd, buffer, size, 0);
666 DISABLE_TIMEOUT(socket);
667 UNMASK_SIGNAL();
668
669 if (ret == -1 && errno != EWOULDBLOCK) {
670 socket->m_error = GSOCK_IOERR;
671 return -1;
672 }
673 if (errno == EWOULDBLOCK) {
674 socket->m_error = GSOCK_WOULDBLOCK;
675 return -1;
676 }
677 return ret;
678 }
679
680 int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
681 {
682 struct sockaddr from;
683 SOCKLEN_T fromlen;
684 int ret;
685
686 fromlen = sizeof(from);
687
688 MASK_SIGNAL();
689 ENABLE_TIMEOUT(socket);
690 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen);
691 DISABLE_TIMEOUT(socket);
692 UNMASK_SIGNAL();
693 if (ret == -1 && errno != EWOULDBLOCK) {
694 socket->m_error = GSOCK_IOERR;
695 return -1;
696 }
697 if (errno == EWOULDBLOCK) {
698 socket->m_error = GSOCK_WOULDBLOCK;
699 return -1;
700 }
701
702 /* Translate a system address into a GSocket address */
703 if (!socket->m_peer) {
704 socket->m_peer = GAddress_new();
705 if (!socket->m_peer) {
706 socket->m_error = GSOCK_MEMERR;
707 return -1;
708 }
709 }
710 if (_GAddress_translate_from(socket->m_peer, &from, fromlen) != GSOCK_NOERROR)
711 return -1;
712
713 return ret;
714 }
715
716 int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
717 {
718 int ret;
719
720 MASK_SIGNAL();
721 ENABLE_TIMEOUT(socket);
722 ret = send(socket->m_fd, buffer, size, 0);
723 DISABLE_TIMEOUT(socket);
724 UNMASK_SIGNAL();
725 if (ret == -1 && errno != EWOULDBLOCK) {
726 socket->m_error = GSOCK_IOERR;
727 return -1;
728 }
729 if (errno == EWOULDBLOCK) {
730 socket->m_error = GSOCK_WOULDBLOCK;
731 return -1;
732 }
733 return ret;
734 }
735
736 int _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
746 if (_GAddress_translate_to(socket->m_peer, &addr, &len) != GSOCK_NOERROR) {
747 return -1;
748 }
749
750 MASK_SIGNAL();
751 ENABLE_TIMEOUT(socket);
752 ret = sendto(socket->m_fd, buffer, size, 0, addr, len);
753 DISABLE_TIMEOUT(socket);
754 UNMASK_SIGNAL();
755
756 /* Frees memory allocated from _GAddress_translate_to */
757 free(addr);
758
759 if (ret == -1 && errno != EWOULDBLOCK) {
760 socket->m_error = GSOCK_IOERR;
761 return -1;
762 }
763 if (errno == EWOULDBLOCK) {
764 socket->m_error = GSOCK_WOULDBLOCK;
765 return -1;
766 }
767
768 return ret;
769 }
770
771 void _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
792 void _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
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 */
811 #define CHECK_ADDRESS(address, family, retval) \
812 { \
813 if (address->m_family == GSOCK_NOFAMILY) \
814 if (_GAddress_Init_##family(address) != GSOCK_NOERROR) {\
815 return address->m_error; \
816 }\
817 if (address->m_family != GSOCK_##family) {\
818 address->m_error = GSOCK_INVADDR; \
819 return retval; \
820 } \
821 }
822
823 GAddress *GAddress_new()
824 {
825 GAddress *address;
826
827 address = (GAddress *)malloc(sizeof(GAddress));
828
829 if (address == NULL)
830 return NULL;
831
832 address->m_family = GSOCK_NOFAMILY;
833 address->m_addr = NULL;
834 address->m_len = 0;
835
836 return address;
837 }
838
839 GAddress *GAddress_copy(GAddress *address)
840 {
841 GAddress *addr2;
842
843 assert(address != NULL);
844
845 addr2 = (GAddress *)malloc(sizeof(GAddress));
846
847 if (addr2 == NULL)
848 return NULL;
849
850 memcpy(addr2, address, sizeof(GAddress));
851
852 if (address->m_addr) {
853 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
854 if (addr2->m_addr == NULL) {
855 free(addr2);
856 return NULL;
857 }
858 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
859 }
860
861 return addr2;
862 }
863
864 void GAddress_destroy(GAddress *address)
865 {
866 assert(address != NULL);
867
868 free(address);
869 }
870
871 void GAddress_SetFamily(GAddress *address, GAddressType type)
872 {
873 assert(address != NULL);
874
875 address->m_family = type;
876 }
877
878 GAddressType GAddress_GetFamily(GAddress *address)
879 {
880 assert(address != NULL);
881
882 return address->m_family;
883 }
884
885 GSocketError _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){
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;
894 #ifdef AF_INET6
895 case AF_INET6:
896 address->m_family = GSOCK_INET6;
897 break;
898 #endif
899 default:
900 {
901 address->m_error = GSOCK_INVOP;
902 return GSOCK_INVOP;
903 }
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);
911 if (address->m_addr == NULL) {
912 address->m_error = GSOCK_MEMERR;
913 return GSOCK_MEMERR;
914 }
915 memcpy(address->m_addr, addr, len);
916
917 return GSOCK_NOERROR;
918 }
919
920 GSocketError _GAddress_translate_to(GAddress *address,
921 struct sockaddr **addr, int *len)
922 {
923 if (!address->m_addr) {
924 address->m_error = GSOCK_INVADDR;
925 return GSOCK_INVADDR;
926 }
927
928 *len = address->m_len;
929 *addr = (struct sockaddr *)malloc(address->m_len);
930 if (*addr == NULL) {
931 address->m_error = GSOCK_MEMERR;
932 return GSOCK_MEMERR;
933 }
934
935 memcpy(*addr, address->m_addr, address->m_len);
936 return GSOCK_NOERROR;
937 }
938
939 /*
940 * -------------------------------------------------------------------------
941 * Internet address family
942 * -------------------------------------------------------------------------
943 */
944
945 GSocketError _GAddress_Init_INET(GAddress *address)
946 {
947 address->m_addr = (struct sockaddr *)malloc(sizeof(struct sockaddr_in));
948 if (address->m_addr == NULL) {
949 address->m_error = GSOCK_MEMERR;
950 return GSOCK_MEMERR;
951 }
952
953 address->m_len = sizeof(struct sockaddr_in);
954
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;
959
960 return GSOCK_NOERROR;
961 }
962
963 GSocketError 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
974 /* If it is a numeric host name, convert it now */
975 #if defined(HAVE_INET_ATON)
976 if (inet_aton(hostname, addr) == 0) {
977 #elif defined(HAVE_INET_ADDR)
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
984 struct in_addr *array_addr;
985
986 /* It is a real name, we solve it */
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
997 GSocketError 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
1012 GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1013 const char *protocol)
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;
1023 return GSOCK_INVPORT;
1024 }
1025
1026 se = getservbyname(port, protocol);
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
1047 GSocketError 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
1060 GSocketError 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
1083 unsigned 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
1095 unsigned 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
1112 GSocketError _GAddress_Init_UNIX(GAddress *address)
1113 {
1114 address->m_addr = (struct sockaddr *)malloc(address->m_len);
1115 if (address->m_addr == NULL) {
1116 address->m_error = GSOCK_MEMERR;
1117 return GSOCK_MEMERR;
1118 }
1119
1120 address->m_len = sizeof(struct sockaddr_un);
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;
1125
1126 return TRUE;
1127 }
1128
1129 GSocketError 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
1143 GSocketError 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 }
1156
1157 #endif
1158 /* wxUSE_SOCKETS */