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