wxSocketImpl::Shutdown() doesn't need to be virtual, its implementation can the same...
[wxWidgets.git] / src / unix / sockunix.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/sockunix.cpp
3 // Purpose: wxSocketImpl implementation for Unix systems
4 // Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia, David Elliott,
5 // Vadim Zeitlin
6 // Created: April 1997
7 // RCS-ID: $Id$
8 // Copyright: (c) 1997 Guilhem Lavaux
9 // (c) 2008 Vadim Zeitlin
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13
14 #include "wx/wxprec.h"
15
16 #if wxUSE_SOCKETS
17
18 #include "wx/private/fd.h"
19 #include "wx/private/socket.h"
20 #include "wx/unix/private/sockunix.h"
21
22 #if defined(__VISAGECPP__)
23 #define BSD_SELECT /* use Berkeley Sockets select */
24 #endif
25
26 #if defined(__WATCOMC__)
27 #include <errno.h>
28 #include <nerrno.h>
29 #endif
30
31 #include <assert.h>
32 #include <sys/types.h>
33 #ifdef __VISAGECPP__
34 #include <string.h>
35 #include <sys/time.h>
36 #include <types.h>
37 #include <netinet/in.h>
38 #endif
39 #include <netdb.h>
40 #include <sys/ioctl.h>
41
42 #ifdef HAVE_SYS_SELECT_H
43 # include <sys/select.h>
44 #endif
45
46 #ifdef __VMS__
47 #include <socket.h>
48 struct sockaddr_un
49 {
50 u_char sun_len; /* sockaddr len including null */
51 u_char sun_family; /* AF_UNIX */
52 char sun_path[108]; /* path name (gag) */
53 };
54 #else
55 #include <sys/socket.h>
56 #include <sys/un.h>
57 #endif
58
59 #ifndef __VISAGECPP__
60 #include <sys/time.h>
61 #include <netinet/in.h>
62 #include <arpa/inet.h>
63 #include <errno.h>
64 #include <string.h>
65 #include <unistd.h>
66 #else
67 #include <nerrno.h>
68 # if __IBMCPP__ < 400
69 #include <machine/endian.h>
70 #include <socket.h>
71 #include <ioctl.h>
72 #include <select.h>
73 #include <unistd.h>
74
75 #define EBADF SOCEBADF
76
77 # ifdef min
78 # undef min
79 # endif
80 # else
81 #include <sys/socket.h>
82 #include <sys/ioctl.h>
83 #include <sys/select.h>
84
85 #define close(a) soclose(a)
86 #define select(a,b,c,d,e) bsdselect(a,b,c,d,e)
87 int _System bsdselect(int,
88 struct fd_set *,
89 struct fd_set *,
90 struct fd_set *,
91 struct timeval *);
92 int _System soclose(int);
93 # endif
94 #endif
95 #ifdef __EMX__
96 #include <sys/select.h>
97 #endif
98
99 #include <stdio.h>
100 #include <stdlib.h>
101 #include <stddef.h>
102 #include <ctype.h>
103 #ifdef sun
104 # include <sys/filio.h>
105 #endif
106 #ifdef sgi
107 # include <bstring.h>
108 #endif
109 #ifdef _AIX
110 # include <strings.h>
111 #endif
112 #include <signal.h>
113
114 #ifndef WX_SOCKLEN_T
115
116 #ifdef VMS
117 # define WX_SOCKLEN_T unsigned int
118 #else
119 # ifdef __GLIBC__
120 # if __GLIBC__ == 2
121 # define WX_SOCKLEN_T socklen_t
122 # endif
123 # elif defined(__WXMAC__)
124 # define WX_SOCKLEN_T socklen_t
125 # else
126 # define WX_SOCKLEN_T int
127 # endif
128 #endif
129
130 #endif /* SOCKLEN_T */
131
132 #ifndef SOCKOPTLEN_T
133 #define SOCKOPTLEN_T WX_SOCKLEN_T
134 #endif
135
136 /* UnixWare reportedly needs this for FIONBIO definition */
137 #ifdef __UNIXWARE__
138 #include <sys/filio.h>
139 #endif
140
141 /*
142 * INADDR_BROADCAST is identical to INADDR_NONE which is not defined
143 * on all systems. INADDR_BROADCAST should be fine to indicate an error.
144 */
145 #ifndef INADDR_NONE
146 #define INADDR_NONE INADDR_BROADCAST
147 #endif
148
149 #if defined(__VISAGECPP__) || defined(__WATCOMC__)
150
151 #define MASK_SIGNAL() {
152 #define UNMASK_SIGNAL() }
153
154 #else
155 extern "C" { typedef void (*wxSigHandler)(int); }
156
157 #define MASK_SIGNAL() \
158 { \
159 wxSigHandler old_handler = signal(SIGPIPE, SIG_IGN);
160
161 #define UNMASK_SIGNAL() \
162 signal(SIGPIPE, old_handler); \
163 }
164
165 #endif
166
167 /* If a SIGPIPE is issued by a socket call on a remotely closed socket,
168 the program will "crash" unless it explicitly handles the SIGPIPE.
169 By using MSG_NOSIGNAL, the SIGPIPE is suppressed. Later, we will
170 use SO_NOSIGPIPE (if available), the BSD equivalent. */
171 #ifdef MSG_NOSIGNAL
172 # define GSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
173 #else /* MSG_NOSIGNAL not available (FreeBSD including OS X) */
174 # define GSOCKET_MSG_NOSIGNAL 0
175 #endif /* MSG_NOSIGNAL */
176
177 // ----------------------------------------------------------------------------
178 // implementation of thread-safe/reentrant functions if they're missing
179 // ----------------------------------------------------------------------------
180
181 #if wxUSE_THREADS && (defined(HAVE_GETHOSTBYNAME) || defined(HAVE_GETSERVBYNAME))
182 # include "wx/thread.h"
183 #endif
184
185 #if defined(HAVE_GETHOSTBYNAME)
186 static struct hostent * deepCopyHostent(struct hostent *h,
187 const struct hostent *he,
188 char *buffer, int size, int *err)
189 {
190 /* copy old structure */
191 memcpy(h, he, sizeof(struct hostent));
192
193 /* copy name */
194 int len = strlen(h->h_name);
195 if (len > size)
196 {
197 *err = ENOMEM;
198 return NULL;
199 }
200 memcpy(buffer, h->h_name, len);
201 buffer[len] = '\0';
202 h->h_name = buffer;
203
204 /* track position in the buffer */
205 int pos = len + 1;
206
207 /* reuse len to store address length */
208 len = h->h_length;
209
210 /* ensure pointer alignment */
211 unsigned int misalign = sizeof(char *) - pos%sizeof(char *);
212 if(misalign < sizeof(char *))
213 pos += misalign;
214
215 /* leave space for pointer list */
216 char **p = h->h_addr_list, **q;
217 char **h_addr_list = (char **)(buffer + pos);
218 while(*(p++) != 0)
219 pos += sizeof(char *);
220
221 /* copy addresses and fill new pointer list */
222 for (p = h->h_addr_list, q = h_addr_list; *p != 0; p++, q++)
223 {
224 if (size < pos + len)
225 {
226 *err = ENOMEM;
227 return NULL;
228 }
229 memcpy(buffer + pos, *p, len); /* copy content */
230 *q = buffer + pos; /* set copied pointer to copied content */
231 pos += len;
232 }
233 *++q = 0; /* null terminate the pointer list */
234 h->h_addr_list = h_addr_list; /* copy pointer to pointers */
235
236 /* ensure word alignment of pointers */
237 misalign = sizeof(char *) - pos%sizeof(char *);
238 if(misalign < sizeof(char *))
239 pos += misalign;
240
241 /* leave space for pointer list */
242 p = h->h_aliases;
243 char **h_aliases = (char **)(buffer + pos);
244 while(*(p++) != 0)
245 pos += sizeof(char *);
246
247 /* copy aliases and fill new pointer list */
248 for (p = h->h_aliases, q = h_aliases; *p != 0; p++, q++)
249 {
250 len = strlen(*p);
251 if (size <= pos + len)
252 {
253 *err = ENOMEM;
254 return NULL;
255 }
256 memcpy(buffer + pos, *p, len); /* copy content */
257 buffer[pos + len] = '\0';
258 *q = buffer + pos; /* set copied pointer to copied content */
259 pos += len + 1;
260 }
261 *++q = 0; /* null terminate the pointer list */
262 h->h_aliases = h_aliases; /* copy pointer to pointers */
263
264 return h;
265 }
266 #endif
267
268 #if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS
269 static wxMutex nameLock;
270 #endif
271 struct hostent * wxGethostbyname_r(const char *hostname, struct hostent *h,
272 void *buffer, int size, int *err)
273
274 {
275 struct hostent *he = NULL;
276 *err = 0;
277 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
278 if (gethostbyname_r(hostname, h, (char*)buffer, size, &he, err))
279 he = NULL;
280 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
281 he = gethostbyname_r(hostname, h, (char*)buffer, size, err);
282 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
283 if (gethostbyname_r(hostname, h, (struct hostent_data*) buffer))
284 {
285 he = NULL;
286 *err = h_errno;
287 }
288 else
289 he = h;
290 #elif defined(HAVE_GETHOSTBYNAME)
291 #if wxUSE_THREADS
292 wxMutexLocker locker(nameLock);
293 #endif
294 he = gethostbyname(hostname);
295 if (!he)
296 *err = h_errno;
297 else
298 he = deepCopyHostent(h, he, (char*)buffer, size, err);
299 #endif
300 return he;
301 }
302
303 #if defined(HAVE_GETHOSTBYNAME) && wxUSE_THREADS
304 static wxMutex addrLock;
305 #endif
306 struct hostent * wxGethostbyaddr_r(const char *addr_buf, int buf_size,
307 int proto, struct hostent *h,
308 void *buffer, int size, int *err)
309 {
310 struct hostent *he = NULL;
311 *err = 0;
312 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
313 if (gethostbyaddr_r(addr_buf, buf_size, proto, h,
314 (char*)buffer, size, &he, err))
315 he = NULL;
316 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
317 he = gethostbyaddr_r(addr_buf, buf_size, proto, h, (char*)buffer, size, err);
318 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
319 if (gethostbyaddr_r(addr_buf, buf_size, proto, h,
320 (struct hostent_data*) buffer))
321 {
322 he = NULL;
323 *err = h_errno;
324 }
325 else
326 he = h;
327 #elif defined(HAVE_GETHOSTBYNAME)
328 #if wxUSE_THREADS
329 wxMutexLocker locker(addrLock);
330 #endif
331 he = gethostbyaddr(addr_buf, buf_size, proto);
332 if (!he)
333 *err = h_errno;
334 else
335 he = deepCopyHostent(h, he, (char*)buffer, size, err);
336 #endif
337 return he;
338 }
339
340 #if defined(HAVE_GETSERVBYNAME)
341 static struct servent * deepCopyServent(struct servent *s,
342 const struct servent *se,
343 char *buffer, int size)
344 {
345 /* copy plain old structure */
346 memcpy(s, se, sizeof(struct servent));
347
348 /* copy name */
349 int len = strlen(s->s_name);
350 if (len >= size)
351 {
352 return NULL;
353 }
354 memcpy(buffer, s->s_name, len);
355 buffer[len] = '\0';
356 s->s_name = buffer;
357
358 /* track position in the buffer */
359 int pos = len + 1;
360
361 /* copy protocol */
362 len = strlen(s->s_proto);
363 if (pos + len >= size)
364 {
365 return NULL;
366 }
367 memcpy(buffer + pos, s->s_proto, len);
368 buffer[pos + len] = '\0';
369 s->s_proto = buffer + pos;
370
371 /* track position in the buffer */
372 pos += len + 1;
373
374 /* ensure pointer alignment */
375 unsigned int misalign = sizeof(char *) - pos%sizeof(char *);
376 if(misalign < sizeof(char *))
377 pos += misalign;
378
379 /* leave space for pointer list */
380 char **p = s->s_aliases, **q;
381 char **s_aliases = (char **)(buffer + pos);
382 while(*(p++) != 0)
383 pos += sizeof(char *);
384
385 /* copy addresses and fill new pointer list */
386 for (p = s->s_aliases, q = s_aliases; *p != 0; p++, q++){
387 len = strlen(*p);
388 if (size <= pos + len)
389 {
390 return NULL;
391 }
392 memcpy(buffer + pos, *p, len); /* copy content */
393 buffer[pos + len] = '\0';
394 *q = buffer + pos; /* set copied pointer to copied content */
395 pos += len + 1;
396 }
397 *++q = 0; /* null terminate the pointer list */
398 s->s_aliases = s_aliases; /* copy pointer to pointers */
399 return s;
400 }
401 #endif
402
403 #if defined(HAVE_GETSERVBYNAME) && wxUSE_THREADS
404 static wxMutex servLock;
405 #endif
406 struct servent *wxGetservbyname_r(const char *port, const char *protocol,
407 struct servent *serv, void *buffer, int size)
408 {
409 struct servent *se = NULL;
410 #if defined(HAVE_FUNC_GETSERVBYNAME_R_6)
411 if (getservbyname_r(port, protocol, serv, (char*)buffer, size, &se))
412 se = NULL;
413 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
414 se = getservbyname_r(port, protocol, serv, (char*)buffer, size);
415 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
416 if (getservbyname_r(port, protocol, serv, (struct servent_data*) buffer))
417 se = NULL;
418 else
419 se = serv;
420 #elif defined(HAVE_GETSERVBYNAME)
421 #if wxUSE_THREADS
422 wxMutexLocker locker(servLock);
423 #endif
424 se = getservbyname(port, protocol);
425 if (se)
426 se = deepCopyServent(serv, se, (char*)buffer, size);
427 #endif
428 return se;
429 }
430
431 // ============================================================================
432 // wxSocketImpl implementation
433 // ============================================================================
434
435 /* static */
436 wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
437 {
438 return new wxSocketImplUnix(wxsocket);
439 }
440
441
442 wxSocketError wxSocketImplUnix::GetLastError() const
443 {
444 switch ( errno )
445 {
446 case 0:
447 return wxSOCKET_NOERROR;
448
449 case ENOTSOCK:
450 return wxSOCKET_INVSOCK;
451
452 // unfortunately EAGAIN only has the "would block" meaning for read(),
453 // not for connect() for which it means something rather different but
454 // we can't distinguish between these two situations currently...
455 case EAGAIN:
456 case EINPROGRESS:
457 return wxSOCKET_WOULDBLOCK;
458
459 default:
460 return wxSOCKET_IOERR;
461 }
462 }
463
464 void wxSocketImplUnix::DoEnableEvents(bool flag)
465 {
466 wxSocketManager * const manager = wxSocketManager::Get();
467 if ( flag )
468 {
469 manager->Install_Callback(this, wxSOCKET_INPUT);
470 manager->Install_Callback(this, wxSOCKET_OUTPUT);
471 }
472 else // off
473 {
474 manager->Uninstall_Callback(this, wxSOCKET_INPUT);
475 manager->Uninstall_Callback(this, wxSOCKET_OUTPUT);
476 }
477 }
478
479 /* Generic IO */
480
481 /* Like recv(), send(), ... */
482 int wxSocketImplUnix::Read(void *buffer, int size)
483 {
484 int ret;
485
486 if (m_fd == INVALID_SOCKET || m_server)
487 {
488 m_error = wxSOCKET_INVSOCK;
489 return -1;
490 }
491
492 /* Read the data */
493 if (m_stream)
494 ret = Recv_Stream(buffer, size);
495 else
496 ret = Recv_Dgram(buffer, size);
497
498 /*
499 * If recv returned zero for a TCP socket (if m_stream == NULL, it's an UDP
500 * socket and empty datagrams are possible), then the connection has been
501 * gracefully closed.
502 *
503 * Otherwise, recv has returned an error (-1), in which case we have lost
504 * the socket only if errno does _not_ indicate that there may be more data
505 * to read.
506 */
507 if ((ret == 0) && m_stream)
508 {
509 m_establishing = false;
510 OnStateChange(wxSOCKET_LOST);
511 return 0;
512 }
513 else if (ret == -1)
514 {
515 if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
516 m_error = wxSOCKET_WOULDBLOCK;
517 else
518 m_error = wxSOCKET_IOERR;
519 }
520
521 return ret;
522 }
523
524 int wxSocketImplUnix::Write(const void *buffer, int size)
525 {
526 int ret;
527
528 if (m_fd == INVALID_SOCKET || m_server)
529 {
530 m_error = wxSOCKET_INVSOCK;
531 return -1;
532 }
533
534 /* Write the data */
535 if (m_stream)
536 ret = Send_Stream(buffer, size);
537 else
538 ret = Send_Dgram(buffer, size);
539
540 if (ret == -1)
541 {
542 if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
543 {
544 m_error = wxSOCKET_WOULDBLOCK;
545 }
546 else
547 {
548 m_error = wxSOCKET_IOERR;
549 }
550 }
551
552 return ret;
553 }
554
555 /* Flags */
556
557 int wxSocketImplUnix::Recv_Stream(void *buffer, int size)
558 {
559 int ret;
560 do
561 {
562 ret = recv(m_fd, buffer, size, GSOCKET_MSG_NOSIGNAL);
563 }
564 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
565
566 return ret;
567 }
568
569 int wxSocketImplUnix::Recv_Dgram(void *buffer, int size)
570 {
571 wxSockAddr from;
572 WX_SOCKLEN_T fromlen = sizeof(from);
573 int ret;
574 wxSocketError err;
575
576 fromlen = sizeof(from);
577
578 do
579 {
580 ret = recvfrom(m_fd, buffer, size, 0, (sockaddr*)&from, (WX_SOCKLEN_T *) &fromlen);
581 }
582 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
583
584 if (ret == -1)
585 return -1;
586
587 /* Translate a system address into a wxSocketImplUnix address */
588 if (!m_peer)
589 {
590 m_peer = GAddress_new();
591 if (!m_peer)
592 {
593 m_error = wxSOCKET_MEMERR;
594 return -1;
595 }
596 }
597
598 err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
599 if (err != wxSOCKET_NOERROR)
600 {
601 GAddress_destroy(m_peer);
602 m_peer = NULL;
603 m_error = err;
604 return -1;
605 }
606
607 return ret;
608 }
609
610 int wxSocketImplUnix::Send_Stream(const void *buffer, int size)
611 {
612 int ret;
613
614 MASK_SIGNAL();
615
616 do
617 {
618 ret = send(m_fd, buffer, size, GSOCKET_MSG_NOSIGNAL);
619 }
620 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
621
622 UNMASK_SIGNAL();
623
624 return ret;
625 }
626
627 int wxSocketImplUnix::Send_Dgram(const void *buffer, int size)
628 {
629 struct sockaddr *addr;
630 int len, ret;
631 wxSocketError err;
632
633 if (!m_peer)
634 {
635 m_error = wxSOCKET_INVADDR;
636 return -1;
637 }
638
639 err = _GAddress_translate_to(m_peer, &addr, &len);
640 if (err != wxSOCKET_NOERROR)
641 {
642 m_error = err;
643 return -1;
644 }
645
646 MASK_SIGNAL();
647
648 do
649 {
650 ret = sendto(m_fd, buffer, size, 0, addr, len);
651 }
652 while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
653
654 UNMASK_SIGNAL();
655
656 /* Frees memory allocated from _GAddress_translate_to */
657 free(addr);
658
659 return ret;
660 }
661
662 void wxSocketImplUnix::OnStateChange(wxSocketNotify event)
663 {
664 NotifyOnStateChange(event);
665
666 if ( event == wxSOCKET_LOST )
667 Shutdown();
668 }
669
670 void wxSocketImplUnix::OnReadWaiting()
671 {
672 char c;
673
674 if (m_fd == INVALID_SOCKET)
675 {
676 return;
677 }
678
679 int num = recv(m_fd, &c, 1, MSG_PEEK | GSOCKET_MSG_NOSIGNAL);
680
681 if (num > 0)
682 {
683 OnStateChange(wxSOCKET_INPUT);
684 }
685 else
686 {
687 if (m_server && m_stream)
688 {
689 OnStateChange(wxSOCKET_CONNECTION);
690 }
691 else if (num == 0)
692 {
693 if (m_stream)
694 {
695 /* graceful shutdown */
696 OnStateChange(wxSOCKET_LOST);
697 }
698 else
699 {
700 /* Empty datagram received */
701 OnStateChange(wxSOCKET_INPUT);
702 }
703 }
704 else
705 {
706 /* Do not throw a lost event in cases where the socket isn't really lost */
707 if ((errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINTR))
708 {
709 OnStateChange(wxSOCKET_INPUT);
710 }
711 else
712 {
713 OnStateChange(wxSOCKET_LOST);
714 }
715 }
716 }
717 }
718
719 void wxSocketImplUnix::OnWriteWaiting()
720 {
721 if (m_establishing && !m_server)
722 {
723 int error;
724 SOCKOPTLEN_T len = sizeof(error);
725
726 m_establishing = false;
727
728 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
729
730 if (error)
731 {
732 OnStateChange(wxSOCKET_LOST);
733 }
734 else
735 {
736 OnStateChange(wxSOCKET_CONNECTION);
737 /* We have to fire this event by hand because CONNECTION (for clients)
738 * and OUTPUT are internally the same and we just disabled CONNECTION
739 * events with the above macro.
740 */
741 OnStateChange(wxSOCKET_OUTPUT);
742 }
743 }
744 else
745 {
746 OnStateChange(wxSOCKET_OUTPUT);
747 }
748 }
749
750 void wxSocketImplUnix::OnExceptionWaiting()
751 {
752 wxFAIL_MSG( "not supposed to be called" );
753 }
754
755 /*
756 * -------------------------------------------------------------------------
757 * GAddress
758 * -------------------------------------------------------------------------
759 */
760
761 /* CHECK_ADDRESS verifies that the current address family is either
762 * wxSOCKET_NOFAMILY or wxSOCKET_*family*, and if it is wxSOCKET_NOFAMILY, it
763 * initalizes it to be a wxSOCKET_*family*. In other cases, it returns
764 * an appropiate error code.
765 *
766 * CHECK_ADDRESS_RETVAL does the same but returning 'retval' on error.
767 */
768 #define CHECK_ADDRESS(address, family) \
769 { \
770 if (address->m_family == wxSOCKET_NOFAMILY) \
771 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
772 return address->m_error; \
773 if (address->m_family != wxSOCKET_##family) \
774 { \
775 address->m_error = wxSOCKET_INVADDR; \
776 return wxSOCKET_INVADDR; \
777 } \
778 }
779
780 #define CHECK_ADDRESS_RETVAL(address, family, retval) \
781 { \
782 if (address->m_family == wxSOCKET_NOFAMILY) \
783 if (_GAddress_Init_##family(address) != wxSOCKET_NOERROR) \
784 return retval; \
785 if (address->m_family != wxSOCKET_##family) \
786 { \
787 address->m_error = wxSOCKET_INVADDR; \
788 return retval; \
789 } \
790 }
791
792
793 GAddress *GAddress_new(void)
794 {
795 GAddress *address;
796
797 if ((address = (GAddress *) malloc(sizeof(GAddress))) == NULL)
798 return NULL;
799
800 address->m_family = wxSOCKET_NOFAMILY;
801 address->m_addr = NULL;
802 address->m_len = 0;
803
804 return address;
805 }
806
807 GAddress *GAddress_copy(GAddress *address)
808 {
809 GAddress *addr2;
810
811 assert(address != NULL);
812
813 if ((addr2 = (GAddress *) malloc(sizeof(GAddress))) == NULL)
814 return NULL;
815
816 memcpy(addr2, address, sizeof(GAddress));
817
818 if (address->m_addr && address->m_len > 0)
819 {
820 addr2->m_addr = (struct sockaddr *)malloc(addr2->m_len);
821 if (addr2->m_addr == NULL)
822 {
823 free(addr2);
824 return NULL;
825 }
826 memcpy(addr2->m_addr, address->m_addr, addr2->m_len);
827 }
828
829 return addr2;
830 }
831
832 void GAddress_destroy(GAddress *address)
833 {
834 assert(address != NULL);
835
836 if (address->m_addr)
837 free(address->m_addr);
838
839 free(address);
840 }
841
842 void GAddress_SetFamily(GAddress *address, GAddressType type)
843 {
844 assert(address != NULL);
845
846 address->m_family = type;
847 }
848
849 GAddressType GAddress_GetFamily(GAddress *address)
850 {
851 assert(address != NULL);
852
853 return address->m_family;
854 }
855
856 wxSocketError _GAddress_translate_from(GAddress *address,
857 struct sockaddr *addr, int len)
858 {
859 address->m_realfamily = addr->sa_family;
860 switch (addr->sa_family)
861 {
862 case AF_INET:
863 address->m_family = wxSOCKET_INET;
864 break;
865 case AF_UNIX:
866 address->m_family = wxSOCKET_UNIX;
867 break;
868 #if wxUSE_IPV6
869 case AF_INET6:
870 address->m_family = wxSOCKET_INET6;
871 break;
872 #endif // wxUSE_IPV6
873 default:
874 {
875 address->m_error = wxSOCKET_INVOP;
876 return wxSOCKET_INVOP;
877 }
878 }
879
880 if (address->m_addr)
881 free(address->m_addr);
882
883 address->m_len = len;
884 address->m_addr = (struct sockaddr *)malloc(len);
885
886 if (address->m_addr == NULL)
887 {
888 address->m_error = wxSOCKET_MEMERR;
889 return wxSOCKET_MEMERR;
890 }
891
892 memcpy(address->m_addr, addr, len);
893
894 return wxSOCKET_NOERROR;
895 }
896
897 wxSocketError _GAddress_translate_to(GAddress *address,
898 struct sockaddr **addr, int *len)
899 {
900 if (!address->m_addr)
901 {
902 address->m_error = wxSOCKET_INVADDR;
903 return wxSOCKET_INVADDR;
904 }
905
906 *len = address->m_len;
907 *addr = (struct sockaddr *)malloc(address->m_len);
908 if (*addr == NULL)
909 {
910 address->m_error = wxSOCKET_MEMERR;
911 return wxSOCKET_MEMERR;
912 }
913
914 memcpy(*addr, address->m_addr, address->m_len);
915 return wxSOCKET_NOERROR;
916 }
917
918 /*
919 * -------------------------------------------------------------------------
920 * Internet address family
921 * -------------------------------------------------------------------------
922 */
923
924 wxSocketError _GAddress_Init_INET(GAddress *address)
925 {
926 address->m_len = sizeof(struct sockaddr_in);
927 address->m_addr = (struct sockaddr *) malloc(address->m_len);
928 if (address->m_addr == NULL)
929 {
930 address->m_error = wxSOCKET_MEMERR;
931 return wxSOCKET_MEMERR;
932 }
933
934 address->m_family = wxSOCKET_INET;
935 address->m_realfamily = PF_INET;
936 ((struct sockaddr_in *)address->m_addr)->sin_family = AF_INET;
937 ((struct sockaddr_in *)address->m_addr)->sin_addr.s_addr = INADDR_ANY;
938
939 return wxSOCKET_NOERROR;
940 }
941
942 wxSocketError GAddress_INET_SetHostName(GAddress *address, const char *hostname)
943 {
944 struct hostent *he;
945 struct in_addr *addr;
946
947 assert(address != NULL);
948
949 CHECK_ADDRESS(address, INET);
950
951 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
952
953 /* If it is a numeric host name, convert it now */
954 #if defined(HAVE_INET_ATON)
955 if (inet_aton(hostname, addr) == 0)
956 {
957 #elif defined(HAVE_INET_ADDR)
958 if ( (addr->s_addr = inet_addr(hostname)) == (unsigned)-1 )
959 {
960 #else
961 /* Use gethostbyname by default */
962 #ifndef __WXMAC__
963 int val = 1; /* VA doesn't like constants in conditional expressions */
964 if (val)
965 #endif
966 {
967 #endif
968 struct in_addr *array_addr;
969
970 /* It is a real name, we solve it */
971 struct hostent h;
972 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
973 struct hostent_data buffer;
974 #else
975 char buffer[1024];
976 #endif
977 int err;
978 he = wxGethostbyname_r(hostname, &h, (void*)&buffer, sizeof(buffer), &err);
979 if (he == NULL)
980 {
981 /* Reset to invalid address */
982 addr->s_addr = INADDR_NONE;
983 address->m_error = wxSOCKET_NOHOST;
984 return wxSOCKET_NOHOST;
985 }
986
987 array_addr = (struct in_addr *) *(he->h_addr_list);
988 addr->s_addr = array_addr[0].s_addr;
989 }
990
991 return wxSOCKET_NOERROR;
992 }
993
994
995 wxSocketError GAddress_INET_SetBroadcastAddress(GAddress *address)
996 {
997 return GAddress_INET_SetHostAddress(address, INADDR_BROADCAST);
998 }
999
1000 wxSocketError GAddress_INET_SetAnyAddress(GAddress *address)
1001 {
1002 return GAddress_INET_SetHostAddress(address, INADDR_ANY);
1003 }
1004
1005 wxSocketError GAddress_INET_SetHostAddress(GAddress *address,
1006 unsigned long hostaddr)
1007 {
1008 struct in_addr *addr;
1009
1010 assert(address != NULL);
1011
1012 CHECK_ADDRESS(address, INET);
1013
1014 addr = &(((struct sockaddr_in *)address->m_addr)->sin_addr);
1015 addr->s_addr = htonl(hostaddr);
1016
1017 return wxSOCKET_NOERROR;
1018 }
1019
1020 wxSocketError GAddress_INET_SetPortName(GAddress *address, const char *port,
1021 const char *protocol)
1022 {
1023 struct servent *se;
1024 struct sockaddr_in *addr;
1025
1026 assert(address != NULL);
1027 CHECK_ADDRESS(address, INET);
1028
1029 if (!port)
1030 {
1031 address->m_error = wxSOCKET_INVPORT;
1032 return wxSOCKET_INVPORT;
1033 }
1034
1035 #if defined(HAVE_FUNC_GETSERVBYNAME_R_4)
1036 struct servent_data buffer;
1037 #else
1038 char buffer[1024];
1039 #endif
1040 struct servent serv;
1041 se = wxGetservbyname_r(port, protocol, &serv,
1042 (void*)&buffer, sizeof(buffer));
1043 if (!se)
1044 {
1045 /* the cast to int suppresses compiler warnings about subscript having the
1046 type char */
1047 if (isdigit((int)port[0]))
1048 {
1049 int port_int;
1050
1051 port_int = atoi(port);
1052 addr = (struct sockaddr_in *)address->m_addr;
1053 addr->sin_port = htons(port_int);
1054 return wxSOCKET_NOERROR;
1055 }
1056
1057 address->m_error = wxSOCKET_INVPORT;
1058 return wxSOCKET_INVPORT;
1059 }
1060
1061 addr = (struct sockaddr_in *)address->m_addr;
1062 addr->sin_port = se->s_port;
1063
1064 return wxSOCKET_NOERROR;
1065 }
1066
1067 wxSocketError GAddress_INET_SetPort(GAddress *address, unsigned short port)
1068 {
1069 struct sockaddr_in *addr;
1070
1071 assert(address != NULL);
1072 CHECK_ADDRESS(address, INET);
1073
1074 addr = (struct sockaddr_in *)address->m_addr;
1075 addr->sin_port = htons(port);
1076
1077 return wxSOCKET_NOERROR;
1078 }
1079
1080 wxSocketError GAddress_INET_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1081 {
1082 struct hostent *he;
1083 char *addr_buf;
1084 struct sockaddr_in *addr;
1085
1086 assert(address != NULL);
1087 CHECK_ADDRESS(address, INET);
1088
1089 addr = (struct sockaddr_in *)address->m_addr;
1090 addr_buf = (char *)&(addr->sin_addr);
1091
1092 struct hostent temphost;
1093 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
1094 struct hostent_data buffer;
1095 #else
1096 char buffer[1024];
1097 #endif
1098 int err;
1099 he = wxGethostbyaddr_r(addr_buf, sizeof(addr->sin_addr), AF_INET, &temphost,
1100 (void*)&buffer, sizeof(buffer), &err);
1101 if (he == NULL)
1102 {
1103 address->m_error = wxSOCKET_NOHOST;
1104 return wxSOCKET_NOHOST;
1105 }
1106
1107 strncpy(hostname, he->h_name, sbuf);
1108
1109 return wxSOCKET_NOERROR;
1110 }
1111
1112 unsigned long GAddress_INET_GetHostAddress(GAddress *address)
1113 {
1114 struct sockaddr_in *addr;
1115
1116 assert(address != NULL);
1117 CHECK_ADDRESS_RETVAL(address, INET, 0);
1118
1119 addr = (struct sockaddr_in *)address->m_addr;
1120
1121 return ntohl(addr->sin_addr.s_addr);
1122 }
1123
1124 unsigned short GAddress_INET_GetPort(GAddress *address)
1125 {
1126 struct sockaddr_in *addr;
1127
1128 assert(address != NULL);
1129 CHECK_ADDRESS_RETVAL(address, INET, 0);
1130
1131 addr = (struct sockaddr_in *)address->m_addr;
1132 return ntohs(addr->sin_port);
1133 }
1134
1135 #if wxUSE_IPV6
1136 /*
1137 * -------------------------------------------------------------------------
1138 * Internet IPv6 address family
1139 * -------------------------------------------------------------------------
1140 */
1141
1142 wxSocketError _GAddress_Init_INET6(GAddress *address)
1143 {
1144 struct in6_addr any_address = IN6ADDR_ANY_INIT;
1145 address->m_len = sizeof(struct sockaddr_in6);
1146 address->m_addr = (struct sockaddr *) malloc(address->m_len);
1147 if (address->m_addr == NULL)
1148 {
1149 address->m_error = wxSOCKET_MEMERR;
1150 return wxSOCKET_MEMERR;
1151 }
1152 memset(address->m_addr,0,address->m_len);
1153
1154 address->m_family = wxSOCKET_INET6;
1155 address->m_realfamily = AF_INET6;
1156 ((struct sockaddr_in6 *)address->m_addr)->sin6_family = AF_INET6;
1157 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = any_address;
1158
1159 return wxSOCKET_NOERROR;
1160 }
1161
1162 wxSocketError GAddress_INET6_SetHostName(GAddress *address, const char *hostname)
1163 {
1164 assert(address != NULL);
1165 CHECK_ADDRESS(address, INET6);
1166
1167 addrinfo hints;
1168 memset( & hints, 0, sizeof( hints ) );
1169 hints.ai_family = AF_INET6;
1170 addrinfo * info = 0;
1171 if ( getaddrinfo( hostname, "0", & hints, & info ) || ! info )
1172 {
1173 address->m_error = wxSOCKET_NOHOST;
1174 return wxSOCKET_NOHOST;
1175 }
1176
1177 memcpy( address->m_addr, info->ai_addr, info->ai_addrlen );
1178 freeaddrinfo( info );
1179 return wxSOCKET_NOERROR;
1180 }
1181
1182 wxSocketError GAddress_INET6_SetAnyAddress(GAddress *address)
1183 {
1184 assert(address != NULL);
1185
1186 CHECK_ADDRESS(address, INET6);
1187
1188 struct in6_addr addr;
1189 memset( & addr, 0, sizeof( addr ) );
1190 return GAddress_INET6_SetHostAddress(address, addr);
1191 }
1192 wxSocketError GAddress_INET6_SetHostAddress(GAddress *address,
1193 struct in6_addr hostaddr)
1194 {
1195 assert(address != NULL);
1196
1197 CHECK_ADDRESS(address, INET6);
1198
1199 ((struct sockaddr_in6 *)address->m_addr)->sin6_addr = hostaddr;
1200
1201 return wxSOCKET_NOERROR;
1202 }
1203
1204 wxSocketError GAddress_INET6_SetPortName(GAddress *address, const char *port,
1205 const char *protocol)
1206 {
1207 struct servent *se;
1208 struct sockaddr_in6 *addr;
1209
1210 assert(address != NULL);
1211 CHECK_ADDRESS(address, INET6);
1212
1213 if (!port)
1214 {
1215 address->m_error = wxSOCKET_INVPORT;
1216 return wxSOCKET_INVPORT;
1217 }
1218
1219 se = getservbyname(port, protocol);
1220 if (!se)
1221 {
1222 if (isdigit(port[0]))
1223 {
1224 int port_int;
1225
1226 port_int = atoi(port);
1227 addr = (struct sockaddr_in6 *)address->m_addr;
1228 addr->sin6_port = htons((u_short) port_int);
1229 return wxSOCKET_NOERROR;
1230 }
1231
1232 address->m_error = wxSOCKET_INVPORT;
1233 return wxSOCKET_INVPORT;
1234 }
1235
1236 addr = (struct sockaddr_in6 *)address->m_addr;
1237 addr->sin6_port = se->s_port;
1238
1239 return wxSOCKET_NOERROR;
1240 }
1241
1242 wxSocketError GAddress_INET6_SetPort(GAddress *address, unsigned short port)
1243 {
1244 struct sockaddr_in6 *addr;
1245
1246 assert(address != NULL);
1247 CHECK_ADDRESS(address, INET6);
1248
1249 addr = (struct sockaddr_in6 *)address->m_addr;
1250 addr->sin6_port = htons(port);
1251
1252 return wxSOCKET_NOERROR;
1253 }
1254
1255 wxSocketError GAddress_INET6_GetHostName(GAddress *address, char *hostname, size_t sbuf)
1256 {
1257 struct hostent *he;
1258 char *addr_buf;
1259 struct sockaddr_in6 *addr;
1260
1261 assert(address != NULL);
1262 CHECK_ADDRESS(address, INET6);
1263
1264 addr = (struct sockaddr_in6 *)address->m_addr;
1265 addr_buf = (char *)&(addr->sin6_addr);
1266
1267 he = gethostbyaddr(addr_buf, sizeof(addr->sin6_addr), AF_INET6);
1268 if (he == NULL)
1269 {
1270 address->m_error = wxSOCKET_NOHOST;
1271 return wxSOCKET_NOHOST;
1272 }
1273
1274 strncpy(hostname, he->h_name, sbuf);
1275
1276 return wxSOCKET_NOERROR;
1277 }
1278
1279 wxSocketError GAddress_INET6_GetHostAddress(GAddress *address,struct in6_addr *hostaddr)
1280 {
1281 assert(address != NULL);
1282 assert(hostaddr != NULL);
1283 CHECK_ADDRESS_RETVAL(address, INET6, wxSOCKET_INVADDR);
1284 *hostaddr = ( (struct sockaddr_in6 *)address->m_addr )->sin6_addr;
1285 return wxSOCKET_NOERROR;
1286 }
1287
1288 unsigned short GAddress_INET6_GetPort(GAddress *address)
1289 {
1290 assert(address != NULL);
1291 CHECK_ADDRESS_RETVAL(address, INET6, 0);
1292
1293 return ntohs( ((struct sockaddr_in6 *)address->m_addr)->sin6_port );
1294 }
1295
1296 #endif // wxUSE_IPV6
1297
1298 /*
1299 * -------------------------------------------------------------------------
1300 * Unix address family
1301 * -------------------------------------------------------------------------
1302 */
1303
1304 #ifndef __VISAGECPP__
1305 wxSocketError _GAddress_Init_UNIX(GAddress *address)
1306 {
1307 address->m_len = sizeof(struct sockaddr_un);
1308 address->m_addr = (struct sockaddr *)malloc(address->m_len);
1309 if (address->m_addr == NULL)
1310 {
1311 address->m_error = wxSOCKET_MEMERR;
1312 return wxSOCKET_MEMERR;
1313 }
1314
1315 address->m_family = wxSOCKET_UNIX;
1316 address->m_realfamily = PF_UNIX;
1317 ((struct sockaddr_un *)address->m_addr)->sun_family = AF_UNIX;
1318 ((struct sockaddr_un *)address->m_addr)->sun_path[0] = 0;
1319
1320 return wxSOCKET_NOERROR;
1321 }
1322
1323 #define UNIX_SOCK_PATHLEN (sizeof(addr->sun_path)/sizeof(addr->sun_path[0]))
1324
1325 wxSocketError GAddress_UNIX_SetPath(GAddress *address, const char *path)
1326 {
1327 struct sockaddr_un *addr;
1328
1329 assert(address != NULL);
1330
1331 CHECK_ADDRESS(address, UNIX);
1332
1333 addr = ((struct sockaddr_un *)address->m_addr);
1334 strncpy(addr->sun_path, path, UNIX_SOCK_PATHLEN);
1335 addr->sun_path[UNIX_SOCK_PATHLEN - 1] = '\0';
1336
1337 return wxSOCKET_NOERROR;
1338 }
1339
1340 wxSocketError GAddress_UNIX_GetPath(GAddress *address, char *path, size_t sbuf)
1341 {
1342 struct sockaddr_un *addr;
1343
1344 assert(address != NULL);
1345 CHECK_ADDRESS(address, UNIX);
1346
1347 addr = (struct sockaddr_un *)address->m_addr;
1348
1349 strncpy(path, addr->sun_path, sbuf);
1350
1351 return wxSOCKET_NOERROR;
1352 }
1353 #endif /* !defined(__VISAGECPP__) */
1354
1355 #endif /* wxUSE_SOCKETS */