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