SocketAddress.cpp revision 309124
1//===-- SocketAddress.cpp ---------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Host/SocketAddress.h"
11#include <stddef.h>
12#include <stdio.h>
13
14// C Includes
15#if !defined(_WIN32)
16#include <arpa/inet.h>
17#else
18#include "lldb/Host/windows/win32.h"
19#endif
20#include <assert.h>
21#include <string.h>
22
23// C++ Includes
24// Other libraries and framework includes
25// Project includes
26
27// WindowsXP needs an inet_ntop implementation
28#ifdef _WIN32
29
30#ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs
31#define INET6_ADDRSTRLEN 46
32#endif
33
34// TODO: implement shortened form "::" for runs of zeros
35const char* inet_ntop(int af, const void * src,
36                      char * dst, socklen_t size)
37{
38    if (size==0)
39    {
40        return nullptr;
41    }
42
43    switch (af)
44    {
45        case AF_INET:
46        {
47            {
48                const char* formatted = inet_ntoa(*static_cast<const in_addr*>(src));
49                if (formatted && strlen(formatted) < size)
50                {
51                    return ::strcpy(dst, formatted);
52                }
53            }
54            return nullptr;
55        case AF_INET6:
56            {
57                char tmp[INET6_ADDRSTRLEN] = {0};
58                const uint16_t* src16 = static_cast<const uint16_t*>(src);
59                int full_size = ::snprintf(tmp, sizeof(tmp),
60                                          "%x:%x:%x:%x:%x:%x:%x:%x",
61                                          ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]),
62                                          ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])
63                                          );
64                if (full_size < static_cast<int>(size))
65                {
66                    return ::strcpy(dst, tmp);
67                }
68                return nullptr;
69            }
70        }
71    }
72    return nullptr;
73}
74#endif
75
76
77using namespace lldb_private;
78
79//----------------------------------------------------------------------
80// SocketAddress constructor
81//----------------------------------------------------------------------
82SocketAddress::SocketAddress ()
83{
84    Clear ();
85}
86
87SocketAddress::SocketAddress (const struct sockaddr &s)
88{
89    m_socket_addr.sa = s;
90}
91
92
93SocketAddress::SocketAddress (const struct sockaddr_in &s)
94{
95    m_socket_addr.sa_ipv4 = s;
96}
97
98
99SocketAddress::SocketAddress (const struct sockaddr_in6 &s)
100{
101    m_socket_addr.sa_ipv6 = s;
102}
103
104
105SocketAddress::SocketAddress (const struct sockaddr_storage &s)
106{
107    m_socket_addr.sa_storage = s;
108}
109
110//----------------------------------------------------------------------
111// SocketAddress copy constructor
112//----------------------------------------------------------------------
113SocketAddress::SocketAddress (const SocketAddress& rhs) :
114    m_socket_addr (rhs.m_socket_addr)
115{
116}
117
118//----------------------------------------------------------------------
119// Destructor
120//----------------------------------------------------------------------
121SocketAddress::~SocketAddress()
122{
123}
124
125void
126SocketAddress::Clear ()
127{
128    memset (&m_socket_addr, 0, sizeof(m_socket_addr));
129}
130
131bool
132SocketAddress::IsValid () const
133{
134    return GetLength () != 0;
135}
136
137static socklen_t
138GetFamilyLength (sa_family_t family)
139{
140    switch (family)
141    {
142        case AF_INET:  return sizeof(struct sockaddr_in);
143        case AF_INET6: return sizeof(struct sockaddr_in6);
144    }
145    assert(0 && "Unsupported address family");
146    return 0;
147}
148
149socklen_t
150SocketAddress::GetLength () const
151{
152#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
153    return m_socket_addr.sa.sa_len;
154#else
155    return GetFamilyLength (GetFamily());
156#endif
157}
158
159socklen_t
160SocketAddress::GetMaxLength ()
161{
162    return sizeof (sockaddr_t);
163}
164
165sa_family_t
166SocketAddress::GetFamily () const
167{
168    return m_socket_addr.sa.sa_family;
169}
170
171void
172SocketAddress::SetFamily (sa_family_t family)
173{
174    m_socket_addr.sa.sa_family = family;
175#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
176    m_socket_addr.sa.sa_len = GetFamilyLength (family);
177#endif
178}
179
180std::string
181SocketAddress::GetIPAddress () const
182{
183    char str[INET6_ADDRSTRLEN] = {0};
184    switch (GetFamily())
185    {
186        case AF_INET:
187            if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str)))
188                return str;
189            break;
190        case AF_INET6:
191            if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str)))
192                return str;
193            break;
194    }
195    return "";
196}
197
198uint16_t
199SocketAddress::GetPort () const
200{
201    switch (GetFamily())
202    {
203        case AF_INET:   return ntohs(m_socket_addr.sa_ipv4.sin_port);
204        case AF_INET6:  return ntohs(m_socket_addr.sa_ipv6.sin6_port);
205    }
206    return 0;
207}
208
209bool
210SocketAddress::SetPort (uint16_t port)
211{
212    switch (GetFamily())
213    {
214        case AF_INET:
215            m_socket_addr.sa_ipv4.sin_port = htons(port);
216            return true;
217
218        case AF_INET6:
219            m_socket_addr.sa_ipv6.sin6_port = htons(port);
220            return true;
221    }
222    return false;
223}
224
225//----------------------------------------------------------------------
226// SocketAddress assignment operator
227//----------------------------------------------------------------------
228const SocketAddress&
229SocketAddress::operator=(const SocketAddress& rhs)
230{
231    if (this != &rhs)
232        m_socket_addr = rhs.m_socket_addr;
233    return *this;
234}
235
236const SocketAddress&
237SocketAddress::operator=(const struct addrinfo *addr_info)
238{
239    Clear();
240    if (addr_info &&
241        addr_info->ai_addr &&
242        addr_info->ai_addrlen > 0&&
243        addr_info->ai_addrlen <= sizeof m_socket_addr)
244    {
245        ::memcpy (&m_socket_addr,
246                  addr_info->ai_addr,
247                  addr_info->ai_addrlen);
248    }
249    return *this;
250}
251
252const SocketAddress&
253SocketAddress::operator=(const struct sockaddr &s)
254{
255    m_socket_addr.sa = s;
256    return *this;
257}
258
259const SocketAddress&
260SocketAddress::operator=(const struct sockaddr_in &s)
261{
262    m_socket_addr.sa_ipv4 = s;
263    return *this;
264}
265
266const SocketAddress&
267SocketAddress::operator=(const struct sockaddr_in6 &s)
268{
269    m_socket_addr.sa_ipv6 = s;
270    return *this;
271}
272
273const SocketAddress&
274SocketAddress::operator=(const struct sockaddr_storage &s)
275{
276    m_socket_addr.sa_storage = s;
277    return *this;
278}
279
280bool
281SocketAddress::getaddrinfo (const char *host,
282                            const char *service,
283                            int ai_family,
284                            int ai_socktype,
285                            int ai_protocol,
286                            int ai_flags)
287{
288    Clear ();
289
290    struct addrinfo hints;
291    memset(&hints, 0, sizeof(hints));
292    hints.ai_family = ai_family;
293    hints.ai_socktype = ai_socktype;
294    hints.ai_protocol = ai_protocol;
295    hints.ai_flags = ai_flags;
296
297    bool result = false;
298    struct addrinfo *service_info_list = NULL;
299    int err = ::getaddrinfo (host, service, &hints, &service_info_list);
300    if (err == 0 && service_info_list)
301    {
302        *this = service_info_list;
303        result = IsValid ();
304    }
305
306    if (service_info_list)
307        ::freeaddrinfo(service_info_list);
308
309    return result;
310}
311
312
313bool
314SocketAddress::SetToLocalhost (sa_family_t family, uint16_t port)
315{
316    switch (family)
317    {
318        case AF_INET:
319            SetFamily (AF_INET);
320            if (SetPort (port))
321            {
322                m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
323                return true;
324            }
325            break;
326
327        case AF_INET6:
328            SetFamily (AF_INET6);
329            if (SetPort (port))
330            {
331                m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback;
332                return true;
333            }
334            break;
335
336    }
337    Clear();
338    return false;
339}
340
341bool
342SocketAddress::SetToAnyAddress (sa_family_t family, uint16_t port)
343{
344    switch (family)
345    {
346        case AF_INET:
347            SetFamily (AF_INET);
348            if (SetPort (port))
349            {
350                m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl (INADDR_ANY);
351                return true;
352            }
353            break;
354
355        case AF_INET6:
356            SetFamily (AF_INET6);
357            if (SetPort (port))
358            {
359                m_socket_addr.sa_ipv6.sin6_addr = in6addr_any;
360                return true;
361            }
362            break;
363
364    }
365    Clear();
366    return false;
367}
368