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