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