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