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