]> git.saurik.com Git - wxWidgets.git/blame - src/common/sckaddr.cpp
make methods available to all ports
[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
acbed114 50#if defined(__UNIX__) && !defined(__WXMSW__)
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
67badd57 95 #ifdef __VISUALC__
87b621a5
VZ
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)
67badd57 100 #pragma warning(disable:4706)
87b621a5
VZ
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>
67badd57
VZ
109 #endif
110 #endif
d98a58c5 111#endif // __WINDOWS__
c9bccf23
VZ
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
ec5756d6
VZ
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
c9bccf23 131#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
ec5756d6
VZ
132 struct wxGethostBuf : hostent_data
133 {
134 wxGethostBuf()
135 {
136 memset(this, 0, sizeof(hostent_data));
137 }
138 };
c9bccf23
VZ
139#else
140 typedef char wxGethostBuf[1024];
141#endif
142
58cccb3b 143#ifdef HAVE_FUNC_GETSERVBYNAME_R_4
ec5756d6
VZ
144 struct wxGetservBuf : servent_data
145 {
5fe43b60 146 wxGetservBuf()
ec5756d6
VZ
147 {
148 memset(this, 0, sizeof(servent_data));
149 }
150 };
c9bccf23
VZ
151#else
152 typedef char wxGetservBuf[1024];
153#endif
154
cf92f487 155#if defined(wxHAS_MT_SAFE_GETBY_FUNCS) || !wxUSE_THREADS
c9bccf23
VZ
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
6c0d0845 176{
c9bccf23
VZ
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)
6c0d0845 191 {
c9bccf23
VZ
192 *err = ENOMEM;
193 return NULL;
6c0d0845 194 }
c9bccf23
VZ
195 memcpy(buffer, h->h_name, len);
196 buffer[len] = '\0';
197 h->h_name = buffer;
6c0d0845 198
c9bccf23
VZ
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)
898c3e88 275 wxUnusedVar(var);
6677f122
VZ
276 *err = gethostbyname_r(hostname, h, &buffer);
277 he = h;
c9bccf23
VZ
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)
898c3e88 307 wxUnusedVar(size);
6677f122
VZ
308 *err = gethostbyaddr_r(addr_buf, buf_size, proto, h, &buffer);
309 he = h;
c9bccf23
VZ
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
6c0d0845 321
c9bccf23 322 return he;
f4ada568
GL
323}
324
c9bccf23
VZ
325#if defined(HAVE_GETSERVBYNAME)
326servent *deepCopyServent(servent *s,
327 servent *se,
328 char *buffer,
329 int size)
1539c2f5 330{
c9bccf23
VZ
331 /* copy plain old structure */
332 memcpy(s, se, sizeof(servent));
6c0d0845 333
c9bccf23
VZ
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,
58cccb3b 392 wxGetservBuf& buffer,
c9bccf23
VZ
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)
898c3e88 401 wxUnusedVar(size);
f6a25e08
VZ
402 if ( getservbyname_r(port, protocol, serv, &buffer) != 0 )
403 return NULL;
c9bccf23
VZ
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;
1539c2f5
VZ
414}
415
c9bccf23
VZ
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
f4ada568 431{
c9bccf23
VZ
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);
f4ada568
GL
471}
472
c9bccf23 473bool wxSockAddressImpl::SetPortName(const wxString& name, const char *protocol)
f4ada568 474{
c9bccf23
VZ
475 // test whether it's a number first
476 unsigned long port;
477 if ( name.ToULong(&port) )
fccb65a2 478 {
c9bccf23
VZ
479 if ( port > 65535 )
480 return false;
fccb65a2 481 }
c9bccf23
VZ
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);
f4ada568
GL
497}
498
c9bccf23
VZ
499// ----------------------------------------------------------------------------
500// INET address family
501// ----------------------------------------------------------------------------
502
503void wxSockAddressImpl::CreateINET()
f4ada568 504{
c9bccf23
VZ
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;
f4ada568
GL
510}
511
c9bccf23 512bool wxSockAddressImpl::SetHostName4(const wxString& name)
acd15a3f 513{
c9bccf23
VZ
514 sockaddr_in * const addr = GET(sockaddr_in);
515 if ( !addr )
516 return false;
517
197380a0 518 const wxScopedCharBuffer namebuf(name.utf8_str());
c9bccf23
VZ
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;
f4ada568 541}
f4ada568 542
c9bccf23
VZ
543bool wxSockAddressImpl::GetHostAddress(wxUint32 *address) const
544{
545 sockaddr_in * const addr = GET(sockaddr_in);
546 if ( !addr )
547 return false;
be4bd463 548
c9bccf23
VZ
549 *address = ntohl(addr->sin_addr.s_addr);
550
551 return true;
552}
553
554bool wxSockAddressImpl::SetHostAddress(wxUint32 address)
be4bd463 555{
c9bccf23
VZ
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;
be4bd463
JS
563}
564
c9bccf23 565wxUint16 wxSockAddressImpl::GetPort4() const
be4bd463 566{
c9bccf23
VZ
567 sockaddr_in * const addr = GET(sockaddr_in);
568 if ( !addr )
569 return 0;
570
571 return ntohs(addr->sin_port);
be4bd463
JS
572}
573
c9bccf23 574bool wxSockAddressImpl::SetPort4(wxUint16 port)
be4bd463 575{
c9bccf23
VZ
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;
be4bd463
JS
583}
584
c9bccf23
VZ
585#if wxUSE_IPV6
586
587// ----------------------------------------------------------------------------
588// INET6 address family
589// ----------------------------------------------------------------------------
a324a7bc 590
c9bccf23 591void wxSockAddressImpl::CreateINET6()
1539c2f5 592{
c9bccf23
VZ
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;
1539c2f5
VZ
598}
599
c9bccf23 600bool wxSockAddressImpl::SetHostName6(const wxString& hostname)
f4ada568 601{
c9bccf23
VZ
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;
a324a7bc 626}
f4ada568 627
c9bccf23 628bool wxSockAddressImpl::GetHostAddress(in6_addr *address) const
a324a7bc 629{
c9bccf23
VZ
630 sockaddr_in6 * const addr = GET(sockaddr_in6);
631 if ( !addr )
632 return false;
633
634 *address = addr->sin6_addr;
635
636 return true;
a324a7bc 637}
f4ada568 638
c9bccf23 639bool wxSockAddressImpl::SetHostAddress(const in6_addr& address)
a324a7bc 640{
c9bccf23
VZ
641 sockaddr_in6 * const addr = GET(sockaddr_in6);
642 if ( !addr )
643 return false;
644
645 addr->sin6_addr = address;
646
647 return true;
f4ada568
GL
648}
649
c9bccf23 650wxUint16 wxSockAddressImpl::GetPort6() const
f4ada568 651{
c9bccf23
VZ
652 sockaddr_in6 * const addr = GET(sockaddr_in6);
653 if ( !addr )
654 return 0;
655
656 return ntohs(addr->sin6_port);
f4ada568
GL
657}
658
c9bccf23 659bool wxSockAddressImpl::SetPort6(wxUint16 port)
f4ada568 660{
c9bccf23
VZ
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;
f4ada568
GL
668}
669
c9bccf23
VZ
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()
f4ada568 690{
c9bccf23
VZ
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';
f4ada568
GL
697}
698
c9bccf23 699bool wxSockAddressImpl::SetPath(const wxString& path)
f4ada568 700{
c9bccf23
VZ
701 sockaddr_un * const addr = GET(sockaddr_un);
702 if ( !addr )
703 return false;
704
197380a0 705 const wxScopedCharBuffer buf(path.utf8_str());
c9bccf23
VZ
706 if ( strlen(buf) >= UNIX_PATH_MAX )
707 return false;
708
709 wxStrlcpy(addr->sun_path, buf, UNIX_PATH_MAX);
710
711 return true;
f4ada568
GL
712}
713
c9bccf23 714wxString wxSockAddressImpl::GetPath() const
be4bd463 715{
c9bccf23
VZ
716 sockaddr_un * const addr = GET(sockaddr_un);
717 if ( !addr )
718 return wxString();
719
720 return wxString::FromUTF8(addr->sun_path);
be4bd463
JS
721}
722
c9bccf23
VZ
723#endif // wxHAS_UNIX_DOMAIN_SOCKETS
724
725#undef GET
726#undef ALLOC
727
728// ----------------------------------------------------------------------------
729// wxSockAddress
730// ----------------------------------------------------------------------------
731
5fab0c8d
VZ
732const sockaddr *wxSockAddress::GetAddressData() const
733{
734 return GetAddress().GetAddr();
735}
736
737int wxSockAddress::GetAddressDataLen() const
738{
739 return GetAddress().GetLen();
740}
741
c9bccf23 742void wxSockAddress::Init()
60edcf45 743{
ed2e973e 744 if ( wxIsMainThread() && !wxSocketBase::IsInitialized() )
c9bccf23
VZ
745 {
746 // we must do it before using any socket functions
747 (void)wxSocketBase::Initialize();
748 }
60edcf45
VZ
749}
750
c9bccf23 751wxSockAddress::wxSockAddress()
d3ea6527 752{
c9bccf23
VZ
753 Init();
754
755 m_impl = new wxSockAddressImpl();
d3ea6527
GRG
756}
757
c9bccf23
VZ
758wxSockAddress::wxSockAddress(const wxSockAddress& other)
759 : wxObject()
f4ada568 760{
c9bccf23 761 Init();
f4ada568 762
c9bccf23 763 m_impl = new wxSockAddressImpl(*other.m_impl);
f4ada568
GL
764}
765
c9bccf23 766wxSockAddress::~wxSockAddress()
f4ada568 767{
c9bccf23 768 delete m_impl;
f4ada568
GL
769}
770
c9bccf23 771void wxSockAddress::SetAddress(const wxSockAddressImpl& address)
ce22d615 772{
c9bccf23
VZ
773 if ( &address != m_impl )
774 {
775 delete m_impl;
776 m_impl = new wxSockAddressImpl(address);
777 }
ce22d615
RD
778}
779
c9bccf23 780wxSockAddress& wxSockAddress::operator=(const wxSockAddress& addr)
d775fa82 781{
c9bccf23
VZ
782 SetAddress(addr.GetAddress());
783
784 return *this;
d9552598
VZ
785}
786
c9bccf23 787void wxSockAddress::Clear()
1d6d8b5d 788{
c9bccf23 789 m_impl->Clear();
1d6d8b5d
JS
790}
791
c9bccf23
VZ
792// ----------------------------------------------------------------------------
793// wxIPaddress
794// ----------------------------------------------------------------------------
f4ada568 795
c9bccf23 796wxSockAddressImpl& wxIPaddress::GetImpl()
f4ada568 797{
c9bccf23
VZ
798 if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC )
799 m_impl->CreateINET();
800
801 return *m_impl;
f4ada568
GL
802}
803
c9bccf23 804bool wxIPaddress::Hostname(const wxString& name)
1539c2f5 805{
c9bccf23
VZ
806 wxCHECK_MSG( !name.empty(), false, "empty host name is invalid" );
807
808 m_origHostname = name;
809
810 return GetImpl().SetHostName(name);
1539c2f5
VZ
811}
812
c9bccf23 813bool wxIPaddress::Service(const wxString& name)
f4ada568 814{
c9bccf23 815 return GetImpl().SetPortName(name, "tcp");
f4ada568
GL
816}
817
c9bccf23 818bool wxIPaddress::Service(unsigned short port)
f4ada568 819{
c9bccf23 820 return GetImpl().SetPort(port);
f4ada568
GL
821}
822
c9bccf23 823bool wxIPaddress::LocalHost()
f4ada568 824{
c9bccf23 825 return Hostname("localhost");
f4ada568
GL
826}
827
c9bccf23 828wxString wxIPaddress::Hostname() const
f4ada568 829{
c9bccf23 830 return GetImpl().GetHostName();
f4ada568
GL
831}
832
c9bccf23 833unsigned short wxIPaddress::Service() const
f4ada568 834{
c9bccf23 835 return GetImpl().GetPort();
f4ada568
GL
836}
837
c9bccf23 838bool wxIPaddress::operator==(const wxIPaddress& addr) const
f4ada568 839{
c9bccf23
VZ
840 return Hostname().Cmp(addr.Hostname()) == 0 &&
841 Service() == addr.Service();
f4ada568
GL
842}
843
c9bccf23
VZ
844bool wxIPaddress::AnyAddress()
845{
846 return GetImpl().SetToAnyAddress();
847}
848
849// ----------------------------------------------------------------------------
850// wxIPV4address
851// ----------------------------------------------------------------------------
852
853void wxIPV4address::DoInitImpl()
be4bd463 854{
c9bccf23
VZ
855 m_impl->CreateINET();
856}
8575ff50 857
c9bccf23
VZ
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";
be4bd463
JS
873}
874
c9bccf23 875wxString wxIPV4address::IPAddress() const
60edcf45 876{
c9bccf23
VZ
877 wxUint32 addr;
878 if ( !GetImpl().GetHostAddress(&addr) )
879 return wxString();
8575ff50 880
c9bccf23
VZ
881 return wxString::Format
882 (
6178debc 883 "%u.%u.%u.%u",
c9bccf23
VZ
884 (addr >> 24) & 0xff,
885 (addr >> 16) & 0xff,
886 (addr >> 8) & 0xff,
887 addr & 0xff
888 );
60edcf45
VZ
889}
890
c9bccf23 891bool wxIPV4address::BroadcastAddress()
be4bd463 892{
c9bccf23
VZ
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");
be4bd463
JS
936}
937
938wxString wxIPV6address::IPAddress() const
d775fa82 939{
c9bccf23
VZ
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;
8575ff50
VZ
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;
be4bd463
JS
984}
985
be4bd463 986#endif // wxUSE_IPV6
f4ada568 987
c9bccf23 988#ifdef wxHAS_UNIX_DOMAIN_SOCKETS
1539c2f5 989
a324a7bc
GL
990// ---------------------------------------------------------------------------
991// wxUNIXaddress
992// ---------------------------------------------------------------------------
f4ada568 993
c9bccf23 994wxSockAddressImpl& wxUNIXaddress::GetUNIX()
f4ada568 995{
c9bccf23
VZ
996 if ( m_impl->GetFamily() == wxSockAddressImpl::FAMILY_UNSPEC )
997 m_impl->CreateUnix();
f4ada568 998
c9bccf23 999 return *m_impl;
f4ada568
GL
1000}
1001
f4ada568
GL
1002void wxUNIXaddress::Filename(const wxString& fname)
1003{
c9bccf23 1004 GetUNIX().SetPath(fname);
f4ada568
GL
1005}
1006
c9bccf23 1007wxString wxUNIXaddress::Filename() const
f4ada568 1008{
c9bccf23 1009 return GetUNIX().GetPath();
f4ada568
GL
1010}
1011
c9bccf23 1012#endif // wxHAS_UNIX_DOMAIN_SOCKETS
35a4dab7 1013
c9bccf23 1014#endif // wxUSE_SOCKETS