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