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