]> git.saurik.com Git - wxWidgets.git/blob - src/common/sckaddr.cpp
Forgot header with OSX prefix
[wxWidgets.git] / src / common / sckaddr.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/sckaddr.cpp
3 // Purpose: Network address manager
4 // Author: Guilhem Lavaux
5 // Created: 26/04/97
6 // Modified by: Vadim Zeitlin to use wxSockAddressImpl on 2008-12-28
7 // RCS-ID: $Id$
8 // Copyright: (c) 1997, 1998 Guilhem Lavaux
9 // (c) 2008 Vadim Zeitlin
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_SOCKETS
29
30 #ifndef WX_PRECOMP
31 #include "wx/object.h"
32 #include "wx/log.h"
33 #include "wx/intl.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <ctype.h>
38
39 #if !defined(__MWERKS__)
40 #include <memory.h>
41 #endif
42 #endif // !WX_PRECOMP
43
44 #include "wx/socket.h"
45 #include "wx/sckaddr.h"
46 #include "wx/private/socket.h"
47 #include "wx/private/sckaddr.h"
48
49 #include <errno.h>
50
51 #ifdef __UNIX__
52 #include <netdb.h>
53 #include <arpa/inet.h>
54 #endif // __UNIX__
55
56 #ifndef INADDR_NONE
57 #define INADDR_NONE INADDR_ANY
58 #endif
59
60 // ----------------------------------------------------------------------------
61 // wxRTTI macros
62 // ----------------------------------------------------------------------------
63
64 IMPLEMENT_ABSTRACT_CLASS(wxSockAddress, wxObject)
65 IMPLEMENT_ABSTRACT_CLASS(wxIPaddress, wxSockAddress)
66 IMPLEMENT_DYNAMIC_CLASS(wxIPV4address, wxIPaddress)
67 #if wxUSE_IPV6
68 IMPLEMENT_DYNAMIC_CLASS(wxIPV6address, wxIPaddress)
69 #endif
70 #if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__)
71 IMPLEMENT_DYNAMIC_CLASS(wxUNIXaddress, wxSockAddress)
72 #endif
73
74 // ============================================================================
75 // implementation of thread-safe/reentrant functions if they're missing
76 // ============================================================================
77
78 // TODO: use POSIX getaddrinfo() (also available in Winsock 2) for simplicity
79 // and to use the same code for IPv4 and IPv6 support
80
81 #ifdef __WXMSW__
82 #define HAVE_INET_ADDR
83
84 #define HAVE_GETHOSTBYNAME
85 #define HAVE_GETSERVBYNAME
86
87 // under MSW getxxxbyname() functions are MT-safe (but not reentrant) so
88 // we don't need to serialize calls to them
89 #define wxHAS_MT_SAFE_GETBY_FUNCS
90
91 #if wxUSE_IPV6
92 // this header does dynamic dispatching of getaddrinfo/freeaddrinfo()
93 // by implementing them in its own code if the system versions are not
94 // available (as is the case for anything < XP)
95 //
96 // NB: if this is not available for the other compilers (so far tested
97 // with MSVC only) we should just use wxDynamicLibrary "manually"
98 #ifdef __VISUALC__
99 // disable a warning occurring in Microsoft own version of this file
100 #pragma warning(disable:4706)
101 #endif
102 #include <wspiapi.h>
103 #ifdef __VISUALC__
104 #pragma warning(default:4706)
105 #endif
106 #endif
107 #endif // __WXMSW__
108
109 // we assume that we have gethostbyaddr_r() if and only if we have
110 // gethostbyname_r() and that it uses the similar conventions to it (see
111 // comment in configure)
112 #define HAVE_GETHOSTBYADDR HAVE_GETHOSTBYNAME
113 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
114 #define HAVE_FUNC_GETHOSTBYADDR_R_3
115 #endif
116 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_5
117 #define HAVE_FUNC_GETHOSTBYADDR_R_5
118 #endif
119 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_6
120 #define HAVE_FUNC_GETHOSTBYADDR_R_6
121 #endif
122
123 // the _r functions need the extra buffer parameter but unfortunately its type
124 // differs between different systems
125 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
126 typedef hostent_data wxGethostBuf;
127 #else
128 typedef char wxGethostBuf[1024];
129 #endif
130
131 #ifdef HAVE_FUNC_GETSERVBYNAME_R_3
132 typedef servent_data wxGetservBuf;
133 #else
134 typedef char wxGetservBuf[1024];
135 #endif
136
137 #ifdef wxHAS_MT_SAFE_GETBY_FUNCS
138 #define wxLOCK_GETBY_MUTEX(name)
139 #else // may need mutexes to protect getxxxbyxxx() calls
140 #if defined(HAVE_GETHOSTBYNAME) || \
141 defined(HAVE_GETHOSTBYADDR) || \
142 defined(HAVE_GETSERVBYNAME)
143 #include "wx/thread.h"
144
145 namespace
146 {
147 // these mutexes are used to serialize
148 wxMutex nameLock, // gethostbyname()
149 addrLock, // gethostbyaddr()
150 servLock; // getservbyname()
151 }
152
153 #define wxLOCK_GETBY_MUTEX(name) wxMutexLocker locker(name ## Lock)
154 #endif // we don't have _r functions
155 #endif // wxUSE_THREADS
156
157 namespace
158 {
159
160 #if defined(HAVE_GETHOSTBYNAME)
161 hostent *deepCopyHostent(hostent *h,
162 const hostent *he,
163 char *buffer,
164 int size,
165 int *err)
166 {
167 /* copy old structure */
168 memcpy(h, he, sizeof(hostent));
169
170 /* copy name */
171 int len = strlen(h->h_name);
172 if (len > size)
173 {
174 *err = ENOMEM;
175 return NULL;
176 }
177 memcpy(buffer, h->h_name, len);
178 buffer[len] = '\0';
179 h->h_name = buffer;
180
181 /* track position in the buffer */
182 int pos = len + 1;
183
184 /* reuse len to store address length */
185 len = h->h_length;
186
187 /* ensure pointer alignment */
188 unsigned int misalign = sizeof(char *) - pos%sizeof(char *);
189 if(misalign < sizeof(char *))
190 pos += misalign;
191
192 /* leave space for pointer list */
193 char **p = h->h_addr_list, **q;
194 char **h_addr_list = (char **)(buffer + pos);
195 while(*(p++) != 0)
196 pos += sizeof(char *);
197
198 /* copy addresses and fill new pointer list */
199 for (p = h->h_addr_list, q = h_addr_list; *p != 0; p++, q++)
200 {
201 if (size < pos + len)
202 {
203 *err = ENOMEM;
204 return NULL;
205 }
206 memcpy(buffer + pos, *p, len); /* copy content */
207 *q = buffer + pos; /* set copied pointer to copied content */
208 pos += len;
209 }
210 *++q = 0; /* null terminate the pointer list */
211 h->h_addr_list = h_addr_list; /* copy pointer to pointers */
212
213 /* ensure word alignment of pointers */
214 misalign = sizeof(char *) - pos%sizeof(char *);
215 if(misalign < sizeof(char *))
216 pos += misalign;
217
218 /* leave space for pointer list */
219 p = h->h_aliases;
220 char **h_aliases = (char **)(buffer + pos);
221 while(*(p++) != 0)
222 pos += sizeof(char *);
223
224 /* copy aliases and fill new pointer list */
225 for (p = h->h_aliases, q = h_aliases; *p != 0; p++, q++)
226 {
227 len = strlen(*p);
228 if (size <= pos + len)
229 {
230 *err = ENOMEM;
231 return NULL;
232 }
233 memcpy(buffer + pos, *p, len); /* copy content */
234 buffer[pos + len] = '\0';
235 *q = buffer + pos; /* set copied pointer to copied content */
236 pos += len + 1;
237 }
238 *++q = 0; /* null terminate the pointer list */
239 h->h_aliases = h_aliases; /* copy pointer to pointers */
240
241 return h;
242 }
243 #endif // HAVE_GETHOSTBYNAME
244
245 hostent *wxGethostbyname_r(const char *hostname,
246 hostent *h,
247 wxGethostBuf buffer,
248 int size,
249 int *err)
250 {
251 hostent *he;
252 #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
253 gethostbyname_r(hostname, h, buffer, size, &he, err);
254 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
255 he = gethostbyname_r(hostname, h, buffer, size, err);
256 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
257 he = gethostbyname_r(hostname, h, &buffer);
258 *err = h_errno;
259 #elif defined(HAVE_GETHOSTBYNAME)
260 wxLOCK_GETBY_MUTEX(name);
261
262 he = gethostbyname(hostname);
263 *err = h_errno;
264
265 if ( he )
266 he = deepCopyHostent(h, he, buffer, size, err);
267 #else
268 #error "No gethostbyname[_r]()"
269 #endif
270
271 return he;
272 }
273
274 hostent *wxGethostbyaddr_r(const char *addr_buf,
275 int buf_size,
276 int proto,
277 hostent *h,
278 wxGethostBuf buffer,
279 int size,
280 int *err)
281 {
282 hostent *he;
283 #if defined(HAVE_FUNC_GETHOSTBYADDR_R_6)
284 gethostbyaddr_r(addr_buf, buf_size, proto, h, buffer, size, &he, err);
285 #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_5)
286 he = gethostbyaddr_r(addr_buf, buf_size, proto, h, buffer, size, err);
287 #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_3)
288 he = gethostbyaddr_r(addr_buf, buf_size, proto, h, buffer);
289 *err = h_errno;
290 #elif defined(HAVE_GETHOSTBYADDR)
291 wxLOCK_GETBY_MUTEX(addr);
292
293 he = gethostbyaddr(addr_buf, buf_size, proto);
294 *err = h_errno;
295
296 if ( he )
297 he = deepCopyHostent(h, he, buffer, size, err);
298 #else
299 #error "No gethostbyaddr[_r]()"
300 #endif
301
302 return he;
303 }
304
305 #if defined(HAVE_GETSERVBYNAME)
306 servent *deepCopyServent(servent *s,
307 servent *se,
308 char *buffer,
309 int size)
310 {
311 /* copy plain old structure */
312 memcpy(s, se, sizeof(servent));
313
314 /* copy name */
315 int len = strlen(s->s_name);
316 if (len >= size)
317 {
318 return NULL;
319 }
320 memcpy(buffer, s->s_name, len);
321 buffer[len] = '\0';
322 s->s_name = buffer;
323
324 /* track position in the buffer */
325 int pos = len + 1;
326
327 /* copy protocol */
328 len = strlen(s->s_proto);
329 if (pos + len >= size)
330 {
331 return NULL;
332 }
333 memcpy(buffer + pos, s->s_proto, len);
334 buffer[pos + len] = '\0';
335 s->s_proto = buffer + pos;
336
337 /* track position in the buffer */
338 pos += len + 1;
339
340 /* ensure pointer alignment */
341 unsigned int misalign = sizeof(char *) - pos%sizeof(char *);
342 if(misalign < sizeof(char *))
343 pos += misalign;
344
345 /* leave space for pointer list */
346 char **p = s->s_aliases, **q;
347 char **s_aliases = (char **)(buffer + pos);
348 while(*(p++) != 0)
349 pos += sizeof(char *);
350
351 /* copy addresses and fill new pointer list */
352 for (p = s->s_aliases, q = s_aliases; *p != 0; p++, q++){
353 len = strlen(*p);
354 if (size <= pos + len)
355 {
356 return NULL;
357 }
358 memcpy(buffer + pos, *p, len); /* copy content */
359 buffer[pos + len] = '\0';
360 *q = buffer + pos; /* set copied pointer to copied content */
361 pos += len + 1;
362 }
363 *++q = 0; /* null terminate the pointer list */
364 s->s_aliases = s_aliases; /* copy pointer to pointers */
365 return s;
366 }
367 #endif // HAVE_GETSERVBYNAME
368
369 servent *wxGetservbyname_r(const char *port,
370 const char *protocol,
371 servent *serv,
372 wxGetservBuf buffer,
373 int size)
374 {
375 servent *se;
376 #if defined(HAVE_FUNC_GETSERVBYNAME_R_6)
377 getservbyname_r(port, protocol, serv, buffer, size, &se);
378 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
379 se = getservbyname_r(port, protocol, serv, buffer, size);
380 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
381 se = getservbyname_r(port, protocol, serv, &buffer);
382 #elif defined(HAVE_GETSERVBYNAME)
383 wxLOCK_GETBY_MUTEX(serv);
384
385 se = getservbyname(port, protocol);
386 if ( se )
387 se = deepCopyServent(serv, se, buffer, size);
388 #else
389 #error "No getservbyname[_r]()"
390 #endif
391 return se;
392 }
393
394 } // anonymous namespace
395
396 // ============================================================================
397 // wxSockAddressImpl implementation
398 // ============================================================================
399
400 // FIXME-VC6: helper macros to call Alloc/Get() hiding the ugly dummy argument
401 #define ALLOC(T) Alloc(static_cast<T *>(NULL))
402 #define GET(T) Get(static_cast<T *>(NULL))
403
404 // ----------------------------------------------------------------------------
405 // INET or INET6 address family
406 // ----------------------------------------------------------------------------
407
408 wxString wxSockAddressImpl::GetHostName() const
409 {
410 const void *addrbuf;
411 int addrbuflen;
412
413 #if wxUSE_IPV6
414 if ( m_family == FAMILY_INET6 )
415 {
416 sockaddr_in6 * const addr6 = GET(sockaddr_in6);
417 addrbuf = &addr6->sin6_addr;
418 addrbuflen = sizeof(addr6->sin6_addr);
419 }
420 else
421 #endif // wxUSE_IPV6
422 {
423 sockaddr_in * const addr = GET(sockaddr_in);
424 if ( !addr )
425 return wxString();
426
427 addrbuf = &addr->sin_addr;
428 addrbuflen = sizeof(addr->sin_addr);
429 }
430
431 hostent he;
432 wxGethostBuf buffer;
433 int err;
434 if ( !wxGethostbyaddr_r
435 (
436 static_cast<const char *>(addrbuf),
437 addrbuflen,
438 m_family,
439 &he,
440 buffer,
441 sizeof(buffer),
442 &err
443 ) )
444 {
445 return wxString();
446 }
447
448 return wxString::FromUTF8(he.h_name);
449 }
450
451 bool wxSockAddressImpl::SetPortName(const wxString& name, const char *protocol)
452 {
453 // test whether it's a number first
454 unsigned long port;
455 if ( name.ToULong(&port) )
456 {
457 if ( port > 65535 )
458 return false;
459 }
460 else // it's a service name
461 {
462 wxGetservBuf buffer;
463 servent se;
464 if ( !wxGetservbyname_r(name.utf8_str(), protocol, &se,
465 buffer, sizeof(buffer)) )
466 return false;
467
468 // s_port is in network byte order and SetPort() uses the host byte
469 // order and we prefer to reuse it from here instead of assigning to
470 // sin_port directly
471 port = ntohs(se.s_port);
472 }
473
474 return SetPort(port);
475 }
476
477 // ----------------------------------------------------------------------------
478 // INET address family
479 // ----------------------------------------------------------------------------
480
481 void wxSockAddressImpl::CreateINET()
482 {
483 wxASSERT_MSG( Is(FAMILY_UNSPEC), "recreating address as different type?" );
484
485 m_family = FAMILY_INET;
486 sockaddr_in * const addr = ALLOC(sockaddr_in);
487 addr->sin_family = FAMILY_INET;
488 }
489
490 bool wxSockAddressImpl::SetHostName4(const wxString& name)
491 {
492 sockaddr_in * const addr = GET(sockaddr_in);
493 if ( !addr )
494 return false;
495
496 const wxUTF8Buf namebuf(name.utf8_str());
497
498 // first check if this is an address in quad dotted notation
499 #if defined(HAVE_INET_ATON)
500 if ( inet_aton(namebuf, &addr->sin_addr) )
501 return true;
502 #elif defined(HAVE_INET_ADDR)
503 addr->sin_addr.s_addr = inet_addr(namebuf);
504 if ( addr->sin_addr.s_addr != INADDR_NONE )
505 return true;
506 #else
507 #error "Neither inet_aton() nor inet_addr() is available?"
508 #endif
509
510 // it's a host name, resolve it
511 hostent he;
512 wxGethostBuf buffer;
513 int err;
514 if ( !wxGethostbyname_r(namebuf, &he, buffer, sizeof(buffer), &err) )
515 return false;
516
517 addr->sin_addr.s_addr = ((in_addr *)he.h_addr)->s_addr;
518 return true;
519 }
520
521 bool wxSockAddressImpl::GetHostAddress(wxUint32 *address) const
522 {
523 sockaddr_in * const addr = GET(sockaddr_in);
524 if ( !addr )
525 return false;
526
527 *address = ntohl(addr->sin_addr.s_addr);
528
529 return true;
530 }
531
532 bool wxSockAddressImpl::SetHostAddress(wxUint32 address)
533 {
534 sockaddr_in * const addr = GET(sockaddr_in);
535 if ( !addr )
536 return false;
537
538 addr->sin_addr.s_addr = htonl(address);
539
540 return true;
541 }
542
543 wxUint16 wxSockAddressImpl::GetPort4() const
544 {
545 sockaddr_in * const addr = GET(sockaddr_in);
546 if ( !addr )
547 return 0;
548
549 return ntohs(addr->sin_port);
550 }
551
552 bool wxSockAddressImpl::SetPort4(wxUint16 port)
553 {
554 sockaddr_in * const addr = GET(sockaddr_in);
555 if ( !addr )
556 return false;
557
558 addr->sin_port = htons(port);
559
560 return true;
561 }
562
563 #if wxUSE_IPV6
564
565 // ----------------------------------------------------------------------------
566 // INET6 address family
567 // ----------------------------------------------------------------------------
568
569 void wxSockAddressImpl::CreateINET6()
570 {
571 wxASSERT_MSG( Is(FAMILY_UNSPEC), "recreating address as different type?" );
572
573 m_family = FAMILY_INET6;
574 sockaddr_in6 * const addr = ALLOC(sockaddr_in6);
575 addr->sin6_family = FAMILY_INET6;
576 }
577
578 bool wxSockAddressImpl::SetHostName6(const wxString& hostname)
579 {
580 sockaddr_in6 * const addr = GET(sockaddr_in6);
581 if ( !addr )
582 return false;
583
584 addrinfo hints;
585 memset(&hints, 0, sizeof(hints));
586 hints.ai_family = AF_INET6;
587
588 addrinfo *info = NULL;
589 int rc = getaddrinfo(hostname.utf8_str(), NULL, &hints, &info);
590 if ( rc )
591 {
592 // use gai_strerror()?
593 return false;
594 }
595
596 wxCHECK_MSG( info, false, "should have info on success" );
597
598 wxASSERT_MSG( int(info->ai_addrlen) == m_len, "unexpected address length" );
599
600 memcpy(addr, info->ai_addr, info->ai_addrlen);
601 freeaddrinfo(info);
602
603 return true;
604 }
605
606 bool wxSockAddressImpl::GetHostAddress(in6_addr *address) const
607 {
608 sockaddr_in6 * const addr = GET(sockaddr_in6);
609 if ( !addr )
610 return false;
611
612 *address = addr->sin6_addr;
613
614 return true;
615 }
616
617 bool wxSockAddressImpl::SetHostAddress(const in6_addr& address)
618 {
619 sockaddr_in6 * const addr = GET(sockaddr_in6);
620 if ( !addr )
621 return false;
622
623 addr->sin6_addr = address;
624
625 return true;
626 }
627
628 wxUint16 wxSockAddressImpl::GetPort6() const
629 {
630 sockaddr_in6 * const addr = GET(sockaddr_in6);
631 if ( !addr )
632 return 0;
633
634 return ntohs(addr->sin6_port);
635 }
636
637 bool wxSockAddressImpl::SetPort6(wxUint16 port)
638 {
639 sockaddr_in6 * const addr = GET(sockaddr_in6);
640 if ( !addr )
641 return false;
642
643 addr->sin6_port = htons(port);
644
645 return true;
646 }
647
648 bool wxSockAddressImpl::SetToAnyAddress6()
649 {
650 static const in6_addr any = IN6ADDR_ANY_INIT;
651
652 return SetHostAddress(any);
653 }
654
655 #endif // wxUSE_IPV6
656
657 #ifdef wxHAS_UNIX_DOMAIN_SOCKETS
658
659 // ----------------------------------------------------------------------------
660 // Unix address family
661 // ----------------------------------------------------------------------------
662
663 #ifndef UNIX_PATH_MAX
664 #define UNIX_PATH_MAX (WXSIZEOF(((sockaddr_un *)NULL)->sun_path))
665 #endif
666
667 void wxSockAddressImpl::CreateUnix()
668 {
669 wxASSERT_MSG( Is(FAMILY_UNSPEC), "recreating address as different type?" );
670
671 m_family = FAMILY_UNIX;
672 sockaddr_un * const addr = ALLOC(sockaddr_un);
673 addr->sun_family = FAMILY_UNIX;
674 addr->sun_path[0] = '\0';
675 }
676
677 bool wxSockAddressImpl::SetPath(const wxString& path)
678 {
679 sockaddr_un * const addr = GET(sockaddr_un);
680 if ( !addr )
681 return false;
682
683 const wxUTF8Buf buf(path.utf8_str());
684 if ( strlen(buf) >= UNIX_PATH_MAX )
685 return false;
686
687 wxStrlcpy(addr->sun_path, buf, UNIX_PATH_MAX);
688
689 return true;
690 }
691
692 wxString wxSockAddressImpl::GetPath() const
693 {
694 sockaddr_un * const addr = GET(sockaddr_un);
695 if ( !addr )
696 return wxString();
697
698 return wxString::FromUTF8(addr->sun_path);
699 }
700
701 #endif // wxHAS_UNIX_DOMAIN_SOCKETS
702
703 #undef GET
704 #undef ALLOC
705
706 // ----------------------------------------------------------------------------
707 // wxSockAddress
708 // ----------------------------------------------------------------------------
709
710 void wxSockAddress::Init()
711 {
712 if ( !wxSocketBase::IsInitialized() )
713 {
714 // we must do it before using any socket functions
715 (void)wxSocketBase::Initialize();
716 }
717 }
718
719 wxSockAddress::wxSockAddress()
720 {
721 Init();
722
723 m_impl = new wxSockAddressImpl();
724 }
725
726 wxSockAddress::wxSockAddress(const wxSockAddress& other)
727 : wxObject()
728 {
729 Init();
730
731 m_impl = new wxSockAddressImpl(*other.m_impl);
732 }
733
734 wxSockAddress::~wxSockAddress()
735 {
736 delete m_impl;
737 }
738
739 void wxSockAddress::SetAddress(const wxSockAddressImpl& address)
740 {
741 if ( &address != m_impl )
742 {
743 delete m_impl;
744 m_impl = new wxSockAddressImpl(address);
745 }
746 }
747
748 wxSockAddress& wxSockAddress::operator=(const wxSockAddress& addr)
749 {
750 SetAddress(addr.GetAddress());
751
752 return *this;
753 }
754
755 void wxSockAddress::Clear()
756 {
757 m_impl->Clear();
758 }
759
760 // ----------------------------------------------------------------------------
761 // wxIPaddress
762 // ----------------------------------------------------------------------------
763
764 wxSockAddressImpl& wxIPaddress::GetImpl()
765 {
766 if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC )
767 m_impl->CreateINET();
768
769 return *m_impl;
770 }
771
772 bool wxIPaddress::Hostname(const wxString& name)
773 {
774 wxCHECK_MSG( !name.empty(), false, "empty host name is invalid" );
775
776 m_origHostname = name;
777
778 return GetImpl().SetHostName(name);
779 }
780
781 bool wxIPaddress::Service(const wxString& name)
782 {
783 return GetImpl().SetPortName(name, "tcp");
784 }
785
786 bool wxIPaddress::Service(unsigned short port)
787 {
788 return GetImpl().SetPort(port);
789 }
790
791 bool wxIPaddress::LocalHost()
792 {
793 return Hostname("localhost");
794 }
795
796 wxString wxIPaddress::Hostname() const
797 {
798 return GetImpl().GetHostName();
799 }
800
801 unsigned short wxIPaddress::Service() const
802 {
803 return GetImpl().GetPort();
804 }
805
806 bool wxIPaddress::operator==(const wxIPaddress& addr) const
807 {
808 return Hostname().Cmp(addr.Hostname()) == 0 &&
809 Service() == addr.Service();
810 }
811
812 bool wxIPaddress::AnyAddress()
813 {
814 return GetImpl().SetToAnyAddress();
815 }
816
817 // ----------------------------------------------------------------------------
818 // wxIPV4address
819 // ----------------------------------------------------------------------------
820
821 void wxIPV4address::DoInitImpl()
822 {
823 m_impl->CreateINET();
824 }
825
826 bool wxIPV4address::Hostname(unsigned long addr)
827 {
828 if ( !GetImpl().SetHostAddress(addr) )
829 {
830 m_origHostname.clear();
831 return false;
832 }
833
834 m_origHostname = Hostname();
835 return true;
836 }
837
838 bool wxIPV4address::IsLocalHost() const
839 {
840 return Hostname() == "localhost" || IPAddress() == "127.0.0.1";
841 }
842
843 wxString wxIPV4address::IPAddress() const
844 {
845 wxUint32 addr;
846 if ( !GetImpl().GetHostAddress(&addr) )
847 return wxString();
848
849 return wxString::Format
850 (
851 "%lu.%lu.%lu.%lu",
852 (addr >> 24) & 0xff,
853 (addr >> 16) & 0xff,
854 (addr >> 8) & 0xff,
855 addr & 0xff
856 );
857 }
858
859 bool wxIPV4address::BroadcastAddress()
860 {
861 return GetImpl().SetToBroadcastAddress();
862 }
863
864 #if wxUSE_IPV6
865
866 // ---------------------------------------------------------------------------
867 // wxIPV6address
868 // ---------------------------------------------------------------------------
869
870 void wxIPV6address::DoInitImpl()
871 {
872 m_impl->CreateINET6();
873 }
874
875 bool wxIPV6address::Hostname(unsigned char addr[16])
876 {
877 unsigned short wk[8];
878 for ( int i = 0; i < 8; ++i )
879 {
880 wk[i] = addr[2*i];
881 wk[i] <<= 8;
882 wk[i] |= addr[2*i+1];
883 }
884
885 return Hostname
886 (
887 wxString::Format
888 (
889 "%x:%x:%x:%x:%x:%x:%x:%x",
890 wk[0], wk[1], wk[2], wk[3], wk[4], wk[5], wk[6], wk[7]
891 )
892 );
893 }
894
895 bool wxIPV6address::IsLocalHost() const
896 {
897 if ( Hostname() == "localhost" )
898 return true;
899
900 wxString addr = IPAddress();
901 return addr == wxT("::1") ||
902 addr == wxT("0:0:0:0:0:0:0:1") ||
903 addr == wxT("::ffff:127.0.0.1");
904 }
905
906 wxString wxIPV6address::IPAddress() const
907 {
908 union
909 {
910 in6_addr addr6;
911 wxUint8 bytes[16];
912 } u;
913
914 if ( !GetImpl().GetHostAddress(&u.addr6) )
915 return wxString();
916
917 const wxUint8 * const addr = u.bytes;
918
919 wxUint16 words[8];
920 int i,
921 prefix_zero_count = 0;
922 for ( i = 0; i < 8; ++i )
923 {
924 words[i] = addr[i*2];
925 words[i] <<= 8;
926 words[i] |= addr[i*2+1];
927 if ( i == prefix_zero_count && words[i] == 0 )
928 ++prefix_zero_count;
929 }
930
931 wxString result;
932 if ( prefix_zero_count == 8 )
933 {
934 result = wxT( "::" );
935 }
936 else if ( prefix_zero_count == 6 && words[5] == 0xFFFF )
937 {
938 // IPv4 mapped
939 result.Printf("::ffff:%d.%d.%d.%d",
940 addr[12], addr[13], addr[14], addr[15]);
941 }
942 else // general case
943 {
944 result = ":";
945 for ( i = prefix_zero_count; i < 8; ++i )
946 {
947 result += wxString::Format(":%x", words[i]);
948 }
949 }
950
951 return result;
952 }
953
954 #endif // wxUSE_IPV6
955
956 #ifdef wxHAS_UNIX_DOMAIN_SOCKETS
957
958 // ---------------------------------------------------------------------------
959 // wxUNIXaddress
960 // ---------------------------------------------------------------------------
961
962 wxSockAddressImpl& wxUNIXaddress::GetUNIX()
963 {
964 if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC )
965 m_impl->CreateUnix();
966
967 return *m_impl;
968 }
969
970 void wxUNIXaddress::Filename(const wxString& fname)
971 {
972 GetUNIX().SetPath(fname);
973 }
974
975 wxString wxUNIXaddress::Filename() const
976 {
977 return GetUNIX().GetPath();
978 }
979
980 #endif // wxHAS_UNIX_DOMAIN_SOCKETS
981
982 #endif // wxUSE_SOCKETS