]> git.saurik.com Git - wxWidgets.git/blame - src/unix/gsocket.c
Added another missing file (wxBufferedStreams doc)
[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>
26
27#include <string.h>
28#include <unistd.h>
29#include <stdio.h>
30#include <stdlib.h>
31
32#ifdef sun
5a96d2f4 33 #include <sys/filio.h>
a324a7bc
GL
34#endif
35
36#ifdef sgi
37 #include <bstring.h>
38#endif
39
40#include <signal.h>
5a96d2f4 41
ca17eff3 42#include "wx/gsocket.h"
a324a7bc
GL
43#include "gsockunx.h"
44
efee48a0 45#ifndef SOCKLEN_T
5a96d2f4
GL
46
47#ifdef __GLIBC__
48# if __GLIBC__ == 2
49# define SOCKLEN_T socklen_t
50# endif
51#else
52# define SOCKLEN_T int
53#endif
54
efee48a0
KB
55#endif
56
a58d5df4
GL
57/* Global initialisers */
58
31989b0b 59bool GSocket_Init()
a58d5df4 60{
31989b0b 61 return TRUE;
a58d5df4
GL
62}
63
64void GSocket_Cleanup()
65{
66}
67
a324a7bc
GL
68/* Constructors / Destructors */
69
70GSocket *GSocket_new()
71{
72 int i;
73 GSocket *socket;
74
75 socket = (GSocket *)malloc(sizeof(GSocket));
76
77 socket->m_fd = -1;
78 for (i=0;i<GSOCK_MAX_EVENT;i++) {
79 socket->m_fbacks[i] = NULL;
80 socket->m_iocalls[i] = FALSE;
81 }
82 socket->m_local = NULL;
83 socket->m_peer = NULL;
84 socket->m_error = GSOCK_NOERROR;
85 socket->m_server = FALSE;
86 socket->m_stream = TRUE;
87 socket->m_gui_dependent = NULL;
88 socket->m_blocking = FALSE;
89
31989b0b 90 /* We initialize the GUI specific entries here */
a324a7bc
GL
91 _GSocket_GUI_Init(socket);
92
93 return socket;
94}
95
96void GSocket_destroy(GSocket *socket)
97{
98 assert(socket != NULL);
99
31989b0b 100 /* First, we check that the socket is really shutdowned */
a324a7bc
GL
101 if (socket->m_fd != -1)
102 GSocket_Shutdown(socket);
103
31989b0b 104 /* We destroy GUI specific variables */
dbd300df
GL
105 _GSocket_GUI_Destroy(socket);
106
31989b0b 107 /* We destroy private addresses */
a324a7bc
GL
108 if (socket->m_local)
109 GAddress_destroy(socket->m_local);
110
111 if (socket->m_peer)
112 GAddress_destroy(socket->m_peer);
113
31989b0b 114 /* We destroy socket itself */
a324a7bc
GL
115 free(socket);
116}
117
118void GSocket_Shutdown(GSocket *socket)
119{
120 int evt;
121
122 assert(socket != NULL);
123
31989b0b 124 /* If socket has been created, we shutdown it */
a324a7bc
GL
125 if (socket->m_fd != -1) {
126 shutdown(socket->m_fd, 2);
127 close(socket->m_fd);
128 socket->m_fd = -1;
129 }
130
31989b0b 131 /* We also disable GUI callbacks */
a324a7bc
GL
132 for (evt=0;evt<GSOCK_MAX_EVENT;evt++)
133 _GSocket_Uninstall_Fallback(socket, evt);
134}
135
136/* Address handling */
137
138GSocketError GSocket_SetLocal(GSocket *socket, GAddress *address)
139{
5a96d2f4
GL
140 assert(socket != NULL);
141
31989b0b
GL
142 if ((socket->m_fd != -1 && !socket->m_server)) {
143 socket->m_error = GSOCK_INVSOCK;
a324a7bc 144 return GSOCK_INVSOCK;
31989b0b 145 }
a324a7bc 146
31989b0b
GL
147 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
148 socket->m_error = GSOCK_INVADDR;
a324a7bc 149 return GSOCK_INVADDR;
31989b0b 150 }
a324a7bc
GL
151
152 if (socket->m_local)
153 GAddress_destroy(socket->m_local);
154
155 socket->m_local = GAddress_copy(address);
156
157 return GSOCK_NOERROR;
158}
159
160GSocketError GSocket_SetPeer(GSocket *socket, GAddress *address)
161{
5a96d2f4 162 assert(socket != NULL);
a324a7bc
GL
163
164 if (address == NULL || address->m_family == GSOCK_NOFAMILY) {
165 socket->m_error = GSOCK_INVADDR;
166 return GSOCK_INVADDR;
167 }
168
169 if (socket->m_peer)
170 GAddress_destroy(socket->m_peer);
171
172 socket->m_peer = GAddress_copy(address);
173
174 return GSOCK_NOERROR;
175}
176
177GAddress *GSocket_GetLocal(GSocket *socket)
178{
179 GAddress *address;
180 struct sockaddr addr;
efee48a0 181 SOCKLEN_T size;
a324a7bc
GL
182
183 assert(socket != NULL);
184
185 if (socket->m_local)
186 return GAddress_copy(socket->m_local);
187
188 if (socket->m_fd == -1) {
189 socket->m_error = GSOCK_INVSOCK;
190 return NULL;
191 }
192
193 size = sizeof(addr);
194
195 if (getsockname(socket->m_fd, &addr, &size) < 0) {
196 socket->m_error = GSOCK_IOERR;
197 return NULL;
198 }
199
200 address = GAddress_new();
201 _GAddress_translate_from(address, &addr, size);
202
203 return address;
204}
205
206GAddress *GSocket_GetPeer(GSocket *socket)
207{
208 assert(socket != NULL);
209
210 if (socket->m_peer)
211 return GAddress_copy(socket->m_peer);
212
213 return NULL;
214}
215
216/* Server specific parts */
217
218/*
219 GSocket_SetServer() setup the socket as a server. It uses the "Local" field
220 of GSocket. "Local" must be set by GSocket_SetLocal() before
221 GSocket_SetServer() is called. GSOCK_INVSOCK if socket has been initialized.
5a96d2f4
GL
222 In case, you haven't yet defined the local address, it returns GSOCK_INVADDR.
223 In the other cases it returns GSOCK_IOERR.
a324a7bc
GL
224*/
225GSocketError GSocket_SetServer(GSocket *sck)
226{
227 int type;
228
229 assert(sck != NULL);
230
231 if (sck->m_fd != -1) {
232 sck->m_error = GSOCK_INVSOCK;
233 return GSOCK_INVSOCK;
234 }
235
236 if (!sck->m_local) {
237 sck->m_error = GSOCK_INVADDR;
238 return GSOCK_INVADDR;
239 }
240
241 if (sck->m_stream)
242 type = SOCK_STREAM;
243 else
244 type = SOCK_DGRAM;
245
246 sck->m_fd = socket(sck->m_local->m_realfamily, type, 0);
247
248 if (sck->m_fd == -1) {
249 sck->m_error = GSOCK_IOERR;
250 return GSOCK_IOERR;
251 }
252
253 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
254 close(sck->m_fd);
255 sck->m_fd = -1;
256 sck->m_error = GSOCK_IOERR;
257 return GSOCK_IOERR;
258 }
259
260 if (listen(sck->m_fd, 5) < 0) {
261 close(sck->m_fd);
262 sck->m_fd = -1;
263 sck->m_error = GSOCK_IOERR;
264 return GSOCK_IOERR;
265 }
266
267 sck->m_server = TRUE;
268
269 return GSOCK_NOERROR;
270
271}
272
273/*
274 GSocket_WaitConnection() waits for an incoming client connection.
275*/
276GSocket *GSocket_WaitConnection(GSocket *socket)
277{
278 GSocket *connection;
279
280 assert(socket != NULL);
281
282 if (socket->m_fd == -1 || !socket->m_server) {
283 socket->m_error = GSOCK_INVSOCK;
284 return NULL;
285 }
286
287 _GSocket_Enable(socket, GSOCK_CONNECTION);
288
289 connection = GSocket_new();
290
291 connection->m_fd = accept(socket->m_fd, NULL, NULL);
292 if (connection->m_fd == -1) {
293 GSocket_destroy(connection);
294 socket->m_error = GSOCK_IOERR;
295 return NULL;
296 }
297
298 connection->m_stream = TRUE;
299 connection->m_server = FALSE;
300 connection->m_oriented = TRUE;
301
302 return connection;
303}
304
305/* Non oriented connections */
306
307GSocketError GSocket_SetNonOriented(GSocket *sck)
308{
309 assert(sck != NULL);
310
311 if (sck->m_fd != -1) {
312 sck->m_error = GSOCK_INVSOCK;
313 return GSOCK_INVSOCK;
314 }
315
316 if (!sck->m_local) {
317 sck->m_error = GSOCK_INVADDR;
318 return GSOCK_INVADDR;
319 }
320
321 sck->m_stream = FALSE;
322 sck->m_server = FALSE;
323 sck->m_oriented = FALSE;
324
325 sck->m_fd = socket(sck->m_local->m_realfamily, SOCK_DGRAM, 0);
326
327 if (bind(sck->m_fd, sck->m_local->m_addr, sck->m_local->m_len) < 0) {
328 close(sck->m_fd);
329 sck->m_fd = -1;
330 sck->m_error = GSOCK_IOERR;
331 return GSOCK_IOERR;
332 }
333
334 return GSOCK_NOERROR;
335}
336
337/* Client specific parts */
338
339/*
340 GSocket_Connect() establishes a client connection to a server using the "Peer"
341 field of GSocket. "Peer" must be set by GSocket_SetPeer() before
342 GSocket_Connect() is called. In the other case, it returns GSOCK_INVADDR.
343*/
344GSocketError GSocket_Connect(GSocket *sck, GSocketStream stream)
345{
346 int type;
347
348 assert(sck != NULL);
349
350 if (sck->m_fd != -1) {
351 sck->m_error = GSOCK_INVSOCK;
352 return GSOCK_INVSOCK;
353 }
354
355 if (!sck->m_peer) {
356 sck->m_error = GSOCK_INVADDR;
357 return GSOCK_INVADDR;
358 }
359
360 sck->m_stream = (stream == GSOCK_STREAMED);
361 sck->m_oriented = TRUE;
362
363 if (sck->m_stream)
364 type = SOCK_STREAM;
365 else
366 type = SOCK_DGRAM;
367
368 sck->m_fd = socket(sck->m_peer->m_realfamily, type, 0);
369
370 if (sck->m_fd == -1) {
371 sck->m_error = GSOCK_IOERR;
372 return GSOCK_IOERR;
373 }
374
375 if (connect(sck->m_fd, sck->m_peer->m_addr,
376 sck->m_peer->m_len) != 0) {
377 close(sck->m_fd);
378 sck->m_fd = -1;
379 sck->m_error = GSOCK_IOERR;
380 return GSOCK_IOERR;
381 }
382
383 sck->m_server = FALSE;
384
385 return GSOCK_NOERROR;
386}
387
388/* Generic IO */
389
390/* Like recv(), send(), ... */
391int GSocket_Read(GSocket *socket, char *buffer, int size)
392{
393 assert(socket != NULL);
394
395 if (socket->m_fd == -1 || socket->m_server) {
396 socket->m_error = GSOCK_INVSOCK;
397 return -1;
398 }
399
400 _GSocket_Enable(socket, GSOCK_INPUT);
401
402 if (socket->m_oriented)
403 return _GSocket_Recv_Stream(socket, buffer, size);
404 else
405 return _GSocket_Recv_Dgram(socket, buffer, size);
406}
407
408int GSocket_Write(GSocket *socket, const char *buffer,
409 int size)
410{
411 assert(socket != NULL);
412
413 if (socket->m_fd == -1 || socket->m_server) {
414 socket->m_error = GSOCK_INVSOCK;
415 return -1;
416 }
417
418 _GSocket_Enable(socket, GSOCK_OUTPUT);
419
420 if (socket->m_oriented)
421 return _GSocket_Send_Stream(socket, buffer, size);
422 else
423 return _GSocket_Send_Dgram(socket, buffer, size);
424}
425
426bool GSocket_DataAvailable(GSocket *socket)
427{
428 fd_set read_set;
429 struct timeval tv;
430
431 assert(socket != NULL);
432
433 if (socket->m_fd == -1 || socket->m_server) {
434 socket->m_error = GSOCK_INVSOCK;
435 return FALSE;
436 }
437
438 FD_ZERO(&read_set);
439 FD_SET(socket->m_fd, &read_set);
440
441 tv.tv_sec = 0;
442 tv.tv_usec = 0;
443
444 select(socket->m_fd+1, &read_set, NULL, NULL, &tv);
445
446 return FD_ISSET(socket->m_fd, &read_set);
447}
448
449/* Flags */
450
451/*
452 GSocket_SetBlocking() puts the socket in non-blocking mode. This is useful
453 if we don't want to wait.
454*/
455void GSocket_SetBlocking(GSocket *socket, bool block)
456{
457 assert(socket != NULL);
458
459 socket->m_blocking = block;
460
461 if (socket->m_fd != -1)
462 ioctl(socket->m_fd, FIONBIO, &block);
463}
464
465/*
466 GSocket_GetError() returns the last error occured on the socket stream.
467*/
468
469GSocketError GSocket_GetError(GSocket *socket)
470{
471 assert(socket != NULL);
472
473 return socket->m_error;
474}
475
476/* Callbacks */
477
478/*
479 Only one fallback is possible for each event (INPUT, OUTPUT, CONNECTION)
480 INPUT: The function is called when there is at least a byte in the
481 input buffer
482 OUTPUT: The function is called when the system is sure the next write call
483 will not block
484 CONNECTION: Two cases is possible:
485 Client socket -> the connection is established
486 Server socket -> a client request a connection
487 LOST: the connection is lost
488
489 SetFallback accepts a combination of these flags so a same callback can
490 receive different events.
491
492 An event is generated only once and its state is reseted when the relative
493 IO call is requested.
494 For example: INPUT -> GSocket_Read()
495 CONNECTION -> GSocket_Accept()
496*/
497void GSocket_SetFallback(GSocket *socket, GSocketEventFlags event,
498 GSocketFallback fallback, char *cdata)
499{
500 int count;
501
502 assert (socket != NULL);
503
504 for (count=0;count<GSOCK_MAX_EVENT;count++) {
505 if ((event & (1 << count)) != 0) {
506 socket->m_fbacks[count] = fallback;
507 socket->m_data[count] = cdata;
508
509 _GSocket_Install_Fallback(socket, count);
510 _GSocket_Enable(socket, count);
511 }
512 }
513}
514
515/*
516 UnsetFallback will disables all fallbacks specified by "event".
517 NOTE: event may be a combination of flags
518*/
519void GSocket_UnsetFallback(GSocket *socket, GSocketEventFlags event)
520{
521 int count = 0;
522
523 assert(socket != NULL);
524
525 for (count=0;count<GSOCK_MAX_EVENT;count++) {
526 if ((event & (1 << count)) != 0) {
527 _GSocket_Disable(socket, count);
528 socket->m_fbacks[count] = NULL;
529 _GSocket_Uninstall_Fallback(socket, count);
530 }
531 }
532}
533
534#define CALL_FALLBACK(socket, event) \
535if (socket->m_iocalls[event] && \
536 socket->m_fbacks[event]) {\
537 _GSocket_Disable(socket, event); \
538 socket->m_fbacks[event](socket, event, \
539 socket->m_data[event]); \
540}
541
542#define MASK_SIGNAL() \
543{ \
544 void (*old_handler)(int); \
545\
546 old_handler = signal(SIGPIPE, SIG_IGN);
547
548#define UNMASK_SIGNAL() \
549 signal(SIGPIPE, old_handler); \
550}
551
552void _GSocket_Enable(GSocket *socket, GSocketEvent event)
553{
554 socket->m_iocalls[event] = TRUE;
555 if (socket->m_fbacks[event])
556 _GSocket_Install_Fallback(socket, event);
557}
558
559void _GSocket_Disable(GSocket *socket, GSocketEvent event)
560{
561 socket->m_iocalls[event] = FALSE;
562 if (socket->m_fbacks[event])
563 _GSocket_Uninstall_Fallback(socket, event);
564}
565
566int _GSocket_Recv_Stream(GSocket *socket, char *buffer, int size)
567{
568 int ret;
569
570 MASK_SIGNAL();
571 ret = recv(socket->m_fd, buffer, size, 0);
572 UNMASK_SIGNAL();
573 if (ret == -1) {
574 socket->m_error = GSOCK_IOERR;
575 return -1;
576 }
577 return ret;
578}
579
580int _GSocket_Recv_Dgram(GSocket *socket, char *buffer, int size)
581{
582 struct sockaddr from;
ca17eff3
RR
583 SOCKLEN_T fromlen;
584 int ret;
a324a7bc
GL
585
586 fromlen = sizeof(from);
587
588 MASK_SIGNAL();
589 ret = recvfrom(socket->m_fd, buffer, size, 0, &from, &fromlen);
590 UNMASK_SIGNAL();
591 if (ret == -1) {
592 socket->m_error = GSOCK_IOERR;
593 return -1;
594 }
595
596 if (!socket->m_peer)
597 socket->m_peer = GAddress_new();
598 _GAddress_translate_from(socket->m_peer, &from, fromlen);
599
600 return ret;
601}
602
603int _GSocket_Send_Stream(GSocket *socket, const char *buffer, int size)
604{
605 int ret;
606
607 MASK_SIGNAL();
608 ret = send(socket->m_fd, buffer, size, 0);
609 UNMASK_SIGNAL();
610 if (ret == -1) {
611 socket->m_error = GSOCK_IOERR;
612 return -1;
613 }
614 return ret;
615}
616
617int _GSocket_Send_Dgram(GSocket *socket, const char *buffer, int size)
618{
619 struct sockaddr *addr;
620 int len, ret;
621
622 if (!socket->m_peer) {
623 socket->m_error = GSOCK_INVADDR;
624 return -1;
625 }
626
627 _GAddress_translate_to(socket->m_peer, &addr, &len);
628
629 MASK_SIGNAL();
630 ret = sendto(socket->m_fd, buffer, size, 0, addr, len);
631 UNMASK_SIGNAL();
632 if (ret == -1) {
633 socket->m_error = GSOCK_IOERR;
634 return -1;
635 }
636
637 free(addr);
638
639 return ret;
640}
641
642void _GSocket_Detected_Read(GSocket *socket)
643{
644 char c;
645 int ret;
646
647 if (socket->m_stream) {
648 ret = recv(socket->m_fd, &c, 1, MSG_PEEK);
649
650 if (ret < 0 && socket->m_server) {
651 CALL_FALLBACK(socket, GSOCK_CONNECTION);
652 return;
653 }
654
655 if (ret > 0) {
656 CALL_FALLBACK(socket, GSOCK_INPUT);
657 } else {
658 CALL_FALLBACK(socket, GSOCK_LOST);
659 }
660 }
661}
662
663void _GSocket_Detected_Write(GSocket *socket)
664{
665 CALL_FALLBACK(socket, GSOCK_OUTPUT);
666}
667
668#undef CALL_FALLBACK
669#undef MASK_SIGNAL
670#undef UNMASK_SIGNAL
671
672/*
673 * -------------------------------------------------------------------------
674 * GAddress
675 * -------------------------------------------------------------------------
676 */
677
678#define CHECK_ADDRESS(address, family, retval) \
679{ \
680 if (address->m_family == GSOCK_NOFAMILY) \
681 _GAddress_Init_##family(address); \
682 if (address->m_family != GSOCK_##family) {\
683 address->m_error = GSOCK_INVADDR; \
684 return retval; \
685 } \
686}
687
688GAddress *GAddress_new()
689{
690 GAddress *address;
691
692 address = (GAddress *)malloc(sizeof(GAddress));
693
694 address->m_family = GSOCK_NOFAMILY;
695 address->m_addr = NULL;
696 address->m_len = 0;
697
698 return address;
699}
700
701GAddress *GAddress_copy(GAddress *address)
702{
703 GAddress *addr2;
704
705 assert(address != NULL);
706
707 addr2 = (GAddress *)malloc(sizeof(GAddress));
708 memcpy(addr2, address, sizeof(GAddress));
709
710 if (address->m_addr) {
711 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
712 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
713 }
714
715 return addr2;
716}
717
718void GAddress_destroy(GAddress *address)
719{
720 assert(address != NULL);
721
722 free(address);
723}
724
725void GAddress_SetFamily(GAddress *address, GAddressType type)
726{
727 assert(address != NULL);
728
729 address->m_family = type;
730}
731
732GAddressType GAddress_GetFamily(GAddress *address)
733{
734 assert(address != NULL);
735
736 return address->m_family;
737}
738
739void _GAddress_translate_from(GAddress *address, struct sockaddr *addr, int len){
740 address->m_realfamily = addr->sa_family;
741 switch (addr->sa_family) {
742 case AF_INET:
743 address->m_family = GSOCK_INET;
744 break;
745 case AF_UNIX:
746 address->m_family = GSOCK_UNIX;
747 break;
efee48a0 748#ifdef AF_INET6
a324a7bc
GL
749 case AF_INET6:
750 address->m_family = GSOCK_INET6;
751 break;
efee48a0 752#endif
a324a7bc 753 default:
ca17eff3 754 {
a324a7bc 755 /* TODO error */
ca17eff3 756 }
a324a7bc
GL
757 }
758
759 if (address->m_addr)
760 free(address->m_addr);
761
762 address->m_len = len;
763 address->m_addr = (struct sockaddr *)malloc(len);
764 memcpy(address->m_addr, addr, len);
765}
766
767void _GAddress_translate_to(GAddress *address,
768 struct sockaddr **addr, int *len)
769{
770 if (!address->m_addr) {
771 /* TODO error */
772 return;
773 }
774
775 *len = address->m_len;
776 *addr = (struct sockaddr *)malloc(address->m_len);
777 memcpy(*addr, address->m_addr, address->m_len);
778}
779
780/*
781 * -------------------------------------------------------------------------
782 * Internet address family
783 * -------------------------------------------------------------------------
784 */
785
786void _GAddress_Init_INET(GAddress *address)
787{
788 address->m_len = sizeof(struct sockaddr_in);
789 address->m_addr = (struct sockaddr *)malloc(address->m_len);
790 address->m_family = GSOCK_INET;
791 address->m_realfamily = PF_INET;
792 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
793 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
794}
795
796GSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
797{
798 struct hostent *he;
799 struct in_addr *addr;
800
801 assert(address != NULL);
802
803 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
804
805 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
806
807 /* only name for the moment */
808 if (inet_aton(hostname, addr) == 0) {
809 struct in_addr *array_addr;
810
811 if ((he = gethostbyname(hostname)) == NULL) {
812 address->m_error = GSOCK_NOHOST;
813 return GSOCK_NOHOST;
814 }
815 array_addr = (struct in_addr *) *(he->h_addr_list);
816 addr->s_addr = array_addr[0].s_addr;
817 }
818 return GSOCK_NOERROR;
819}
820
821GSocketError GAddress_INET_SetHostAddress(GAddress *address,
822 unsigned long hostaddr)
823{
824 struct in_addr *addr;
825
826 assert(address != NULL);
827
828 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
829
830 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
831 addr->s_addr = hostaddr;
832
833 return GSOCK_NOERROR;
834}
835
5a96d2f4
GL
836GSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
837 const char *protocol)
a324a7bc
GL
838{
839 struct servent *se;
840 struct sockaddr_in *addr;
841
842 assert(address != NULL);
843 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
844
845 if (!port) {
846 address->m_error = GSOCK_INVPORT;
847 return GSOCK_INVOP;
848 }
849
850 /* TODO: TCP or UDP */
5a96d2f4 851 se = getservbyname(port, protocol);
a324a7bc
GL
852 if (!se) {
853 if (isdigit(port[0])) {
854 int port_int;
855
856 port_int = atoi(port);
857 addr = (struct sockaddr_in *)address->m_addr;
858 addr->sin_port = htons(port_int);
859 return GSOCK_NOERROR;
860 }
861
862 address->m_error = GSOCK_INVPORT;
863 return GSOCK_INVPORT;
864 }
865
866 addr = (struct sockaddr_in *)address->m_addr;
867 addr->sin_port = se->s_port;
868
869 return GSOCK_NOERROR;
870}
871
872GSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
873{
874 struct sockaddr_in *addr;
875
876 assert(address != NULL);
877 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
878
879 addr = (struct sockaddr_in *)address->m_addr;
880 addr->sin_port = htons(port);
881
882 return GSOCK_NOERROR;
883}
884
885GSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
886{
887 struct hostent *he;
888 char *addr_buf;
889 struct sockaddr_in *addr;
890
891 assert(address != NULL);
892 CHECK_ADDRESS(address, INET, GSOCK_INVADDR);
893
894 addr = (struct sockaddr_in *)address->m_addr;
895 addr_buf = (char *)&(addr->sin_addr);
896
897 he = gethostbyaddr(addr_buf, sizeof(addr->sin_addr), AF_INET);
898 if (he == NULL) {
899 address->m_error = GSOCK_NOHOST;
900 return GSOCK_NOHOST;
901 }
902
903 strncpy(hostname, he->h_name, sbuf);
904
905 return GSOCK_NOERROR;
906}
907
908unsigned long GAddress_INET_GetHostAddress(GAddress *address)
909{
910 struct sockaddr_in *addr;
911
912 assert(address != NULL);
913 CHECK_ADDRESS(address, INET, 0);
914
915 addr = (struct sockaddr_in *)address->m_addr;
916
917 return addr->sin_addr.s_addr;
918}
919
920unsigned short GAddress_INET_GetPort(GAddress *address)
921{
922 struct sockaddr_in *addr;
923
924 assert(address != NULL);
925 CHECK_ADDRESS(address, INET, 0);
926
927 addr = (struct sockaddr_in *)address->m_addr;
928 return ntohs(addr->sin_port);
929}
930
931/*
932 * -------------------------------------------------------------------------
933 * Unix address family
934 * -------------------------------------------------------------------------
935 */
936
937void _GAddress_Init_UNIX(GAddress *address)
938{
939 address->m_len = sizeof(struct sockaddr_un);
940 address->m_addr = (struct sockaddr *)malloc(address->m_len);
941 address->m_family = GSOCK_UNIX;
942 address->m_realfamily = PF_UNIX;
943 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
944 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
945}
946
947GSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
948{
949 struct sockaddr_un *addr;
950
951 assert(address != NULL);
952
953 CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR);
954
955 addr = ((struct sockaddr_un *)address->m_addr);
956 memcpy(addr->sun_path, path, strlen(path));
957
958 return GSOCK_NOERROR;
959}
960
961GSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
962{
963 struct sockaddr_un *addr;
964
965 assert(address != NULL);
966 CHECK_ADDRESS(address, UNIX, GSOCK_INVADDR);
967
968 addr = (struct sockaddr_un *)address->m_addr;
969
970 strncpy(path, addr->sun_path, sbuf);
971
972 return GSOCK_NOERROR;
973}
813c20a6
VZ
974
975#endif // wxUSE_SOCKETS