SocketAddress.cpp revision 288943
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            {
189                return str;
190            }
191        case AF_INET6:
192            if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str)))
193            {
194                return str;
195            }
196    }
197    return "";
198}
199
200uint16_t
201SocketAddress::GetPort () const
202{
203    switch (GetFamily())
204    {
205        case AF_INET:   return ntohs(m_socket_addr.sa_ipv4.sin_port);
206        case AF_INET6:  return ntohs(m_socket_addr.sa_ipv6.sin6_port);
207    }
208    return 0;
209}
210
211bool
212SocketAddress::SetPort (uint16_t port)
213{
214    switch (GetFamily())
215    {
216        case AF_INET:
217            m_socket_addr.sa_ipv4.sin_port = htons(port);
218            return true;
219
220        case AF_INET6:
221            m_socket_addr.sa_ipv6.sin6_port = htons(port);
222            return true;
223    }
224    return false;
225}
226
227//----------------------------------------------------------------------
228// SocketAddress assignment operator
229//----------------------------------------------------------------------
230const SocketAddress&
231SocketAddress::operator=(const SocketAddress& rhs)
232{
233    if (this != &rhs)
234        m_socket_addr = rhs.m_socket_addr;
235    return *this;
236}
237
238const SocketAddress&
239SocketAddress::operator=(const struct addrinfo *addr_info)
240{
241    Clear();
242    if (addr_info &&
243        addr_info->ai_addr &&
244        addr_info->ai_addrlen > 0&&
245        addr_info->ai_addrlen <= sizeof m_socket_addr)
246    {
247        ::memcpy (&m_socket_addr,
248                  addr_info->ai_addr,
249                  addr_info->ai_addrlen);
250    }
251    return *this;
252}
253
254const SocketAddress&
255SocketAddress::operator=(const struct sockaddr &s)
256{
257    m_socket_addr.sa = s;
258    return *this;
259}
260
261const SocketAddress&
262SocketAddress::operator=(const struct sockaddr_in &s)
263{
264    m_socket_addr.sa_ipv4 = s;
265    return *this;
266}
267
268const SocketAddress&
269SocketAddress::operator=(const struct sockaddr_in6 &s)
270{
271    m_socket_addr.sa_ipv6 = s;
272    return *this;
273}
274
275const SocketAddress&
276SocketAddress::operator=(const struct sockaddr_storage &s)
277{
278    m_socket_addr.sa_storage = s;
279    return *this;
280}
281
282bool
283SocketAddress::getaddrinfo (const char *host,
284                            const char *service,
285                            int ai_family,
286                            int ai_socktype,
287                            int ai_protocol,
288                            int ai_flags)
289{
290    Clear ();
291
292    struct addrinfo hints;
293    memset(&hints, 0, sizeof(hints));
294    hints.ai_family = ai_family;
295    hints.ai_socktype = ai_socktype;
296    hints.ai_protocol = ai_protocol;
297    hints.ai_flags = ai_flags;
298
299    bool result = false;
300    struct addrinfo *service_info_list = NULL;
301    int err = ::getaddrinfo (host, service, &hints, &service_info_list);
302    if (err == 0 && service_info_list)
303    {
304        *this = service_info_list;
305        result = IsValid ();
306    }
307
308    :: freeaddrinfo (service_info_list);
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