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