]> git.saurik.com Git - wxWidgets.git/blob - src/common/sckaddr.cpp
Improve horizontal scrolling in wxRibbonControl.
[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 #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
63 IMPLEMENT_ABSTRACT_CLASS(wxSockAddress, wxObject)
64 IMPLEMENT_ABSTRACT_CLASS(wxIPaddress, wxSockAddress)
65 IMPLEMENT_DYNAMIC_CLASS(wxIPV4address, wxIPaddress)
66 #if wxUSE_IPV6
67 IMPLEMENT_DYNAMIC_CLASS(wxIPV6address, wxIPaddress)
68 #endif
69 #if defined(__UNIX__) && !defined(__WINDOWS__) && !defined(__WINE__)
70 IMPLEMENT_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
175 namespace
176 {
177
178 #if defined(HAVE_GETHOSTBYNAME)
179 hostent *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
263 hostent *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
293 hostent *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)
326 servent *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
389 servent *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
430 wxString 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
473 bool 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
503 void 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
512 bool 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
543 bool 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
554 bool 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
565 wxUint16 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
574 bool 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
591 void 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
600 bool 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
628 bool 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
639 bool 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
650 wxUint16 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
659 bool 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
670 bool 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
689 void 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
699 bool 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
714 wxString 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
732 const sockaddr *wxSockAddress::GetAddressData() const
733 {
734 return GetAddress().GetAddr();
735 }
736
737 int wxSockAddress::GetAddressDataLen() const
738 {
739 return GetAddress().GetLen();
740 }
741
742 void 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
751 wxSockAddress::wxSockAddress()
752 {
753 Init();
754
755 m_impl = new wxSockAddressImpl();
756 }
757
758 wxSockAddress::wxSockAddress(const wxSockAddress& other)
759 : wxObject()
760 {
761 Init();
762
763 m_impl = new wxSockAddressImpl(*other.m_impl);
764 }
765
766 wxSockAddress::~wxSockAddress()
767 {
768 delete m_impl;
769 }
770
771 void 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
780 wxSockAddress& wxSockAddress::operator=(const wxSockAddress& addr)
781 {
782 SetAddress(addr.GetAddress());
783
784 return *this;
785 }
786
787 void wxSockAddress::Clear()
788 {
789 m_impl->Clear();
790 }
791
792 // ----------------------------------------------------------------------------
793 // wxIPaddress
794 // ----------------------------------------------------------------------------
795
796 wxSockAddressImpl& wxIPaddress::GetImpl()
797 {
798 if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC )
799 m_impl->CreateINET();
800
801 return *m_impl;
802 }
803
804 bool 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
813 bool wxIPaddress::Service(const wxString& name)
814 {
815 return GetImpl().SetPortName(name, "tcp");
816 }
817
818 bool wxIPaddress::Service(unsigned short port)
819 {
820 return GetImpl().SetPort(port);
821 }
822
823 bool wxIPaddress::LocalHost()
824 {
825 return Hostname("localhost");
826 }
827
828 wxString wxIPaddress::Hostname() const
829 {
830 return GetImpl().GetHostName();
831 }
832
833 unsigned short wxIPaddress::Service() const
834 {
835 return GetImpl().GetPort();
836 }
837
838 bool wxIPaddress::operator==(const wxIPaddress& addr) const
839 {
840 return Hostname().Cmp(addr.Hostname()) == 0 &&
841 Service() == addr.Service();
842 }
843
844 bool wxIPaddress::AnyAddress()
845 {
846 return GetImpl().SetToAnyAddress();
847 }
848
849 // ----------------------------------------------------------------------------
850 // wxIPV4address
851 // ----------------------------------------------------------------------------
852
853 void wxIPV4address::DoInitImpl()
854 {
855 m_impl->CreateINET();
856 }
857
858 bool 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
870 bool wxIPV4address::IsLocalHost() const
871 {
872 return Hostname() == "localhost" || IPAddress() == "127.0.0.1";
873 }
874
875 wxString 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
891 bool wxIPV4address::BroadcastAddress()
892 {
893 return GetImpl().SetToBroadcastAddress();
894 }
895
896 #if wxUSE_IPV6
897
898 // ---------------------------------------------------------------------------
899 // wxIPV6address
900 // ---------------------------------------------------------------------------
901
902 void wxIPV6address::DoInitImpl()
903 {
904 m_impl->CreateINET6();
905 }
906
907 bool 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
927 bool 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
938 wxString 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
994 wxSockAddressImpl& wxUNIXaddress::GetUNIX()
995 {
996 if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC )
997 m_impl->CreateUnix();
998
999 return *m_impl;
1000 }
1001
1002 void wxUNIXaddress::Filename(const wxString& fname)
1003 {
1004 GetUNIX().SetPath(fname);
1005 }
1006
1007 wxString wxUNIXaddress::Filename() const
1008 {
1009 return GetUNIX().GetPath();
1010 }
1011
1012 #endif // wxHAS_UNIX_DOMAIN_SOCKETS
1013
1014 #endif // wxUSE_SOCKETS