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