C++ Distributed Hash Table
sockaddr.h
1 /*
2  * Copyright (C) 2016 Savoir-faire Linux Inc.
3  * Author : Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
19 #pragma once
20 
21 #include "def.h"
22 
23 #ifndef _WIN32
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #ifdef __ANDROID__
27 typedef uint16_t in_port_t;
28 #endif
29 #else
30 #include <iso646.h>
31 #include <stdint.h>
32 #include <winsock2.h>
33 #include <ws2def.h>
34 #include <ws2tcpip.h>
35 typedef uint16_t sa_family_t;
36 typedef uint16_t in_port_t;
37 #endif
38 
39 #include <string>
40 #include <memory>
41 #include <vector>
42 #include <stdlib.h>
43 
44 #include <cstring>
45 #include <cstddef>
46 
47 namespace dht {
48 
49 OPENDHT_PUBLIC std::string print_addr(const sockaddr* sa, socklen_t slen);
50 OPENDHT_PUBLIC std::string print_addr(const sockaddr_storage& ss, socklen_t sslen);
51 
55 class OPENDHT_PUBLIC SockAddr {
56 public:
57  SockAddr() {}
58  SockAddr(const SockAddr& o) {
59  set(o.get(), o.getLength());
60  }
61  SockAddr(SockAddr&& o) : len(o.len), addr(std::move(o.addr)) {
62  o.len = 0;
63  }
64 
68  SockAddr(const sockaddr* sa, socklen_t length) {
69  if (length > sizeof(sockaddr_storage))
70  throw std::runtime_error("Socket address length is too large");
71  set(sa, length);
72  }
73  SockAddr(const sockaddr* sa) {
74  socklen_t len = 0;
75  if (sa) {
76  if (sa->sa_family == AF_INET)
77  len = sizeof(sockaddr_in);
78  else if(sa->sa_family == AF_INET6)
79  len = sizeof(sockaddr_in6);
80  else
81  throw std::runtime_error("Unknown address family");
82  }
83  set(sa, len);
84  }
85 
89  SockAddr(const sockaddr_storage& ss, socklen_t len) : SockAddr((const sockaddr*)&ss, len) {}
90 
91  static std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {});
92 
93  bool operator<(const SockAddr& o) const {
94  if (len != o.len)
95  return len < o.len;
96  return std::memcmp((const uint8_t*)get(), (const uint8_t*)o.get(), len) < 0;
97  }
98 
99  bool equals(const SockAddr& o) const {
100  return len == o.len
101  && std::memcmp((const uint8_t*)get(), (const uint8_t*)o.get(), len) == 0;
102  }
103  SockAddr& operator=(const SockAddr& o) {
104  set(o.get(), o.getLength());
105  return *this;
106  }
107  SockAddr& operator=(SockAddr&& o) {
108  len = o.len;
109  o.len = 0;
110  addr = std::move(o.addr);
111  return *this;
112  }
113 
114  std::string toString() const {
115  return print_addr(get(), getLength());
116  }
117 
121  sa_family_t getFamily() const { return len > sizeof(sa_family_t) ? addr->sa_family : AF_UNSPEC; }
122 
128  void setFamily(sa_family_t af) {
129  socklen_t new_length;
130  switch(af) {
131  case AF_INET:
132  new_length = sizeof(sockaddr_in);
133  break;
134  case AF_INET6:
135  new_length = sizeof(sockaddr_in6);
136  break;
137  default:
138  new_length = 0;
139  }
140  if (new_length != len) {
141  len = new_length;
142  if (len) addr.reset((sockaddr*)::calloc(len, 1));
143  else addr.reset();
144  }
145  if (len > sizeof(sa_family_t))
146  addr->sa_family = af;
147  }
148 
153  in_port_t getPort() const {
154  switch(getFamily()) {
155  case AF_INET:
156  return ntohs(getIPv4().sin_port);
157  case AF_INET6:
158  return ntohs(getIPv6().sin6_port);
159  default:
160  return 0;
161  }
162  }
167  void setPort(in_port_t p) {
168  switch(getFamily()) {
169  case AF_INET:
170  getIPv4().sin_port = htons(p);
171  break;
172  case AF_INET6:
173  getIPv6().sin6_port = htons(p);
174  break;
175  }
176  }
177 
182  socklen_t getLength() const { return len; }
183 
187  explicit operator bool() const noexcept {
188  return len;
189  }
190 
195  const sockaddr* get() const { return addr.get(); }
196 
201  sockaddr* get() { return addr.get(); }
202 
203  const sockaddr_in& getIPv4() const {
204  return *reinterpret_cast<const sockaddr_in*>(get());
205  }
206  const sockaddr_in6& getIPv6() const {
207  return *reinterpret_cast<const sockaddr_in6*>(get());
208  }
209  sockaddr_in& getIPv4() {
210  return *reinterpret_cast<sockaddr_in*>(get());
211  }
212  sockaddr_in6& getIPv6() {
213  return *reinterpret_cast<sockaddr_in6*>(get());
214  }
215 
219  bool isLoopback() const;
220 
224  bool isPrivate() const;
225 
226  bool isUnspecified() const;
227 
228  bool isMappedIPv4() const;
229  SockAddr getMappedIPv4() const;
230 
235  struct ipCmp {
236  bool operator()(const SockAddr& a, const SockAddr& b) const {
237  if (a.len != b.len)
238  return a.len < b.len;
239  socklen_t start, len;
240  switch(a.getFamily()) {
241  case AF_INET:
242  start = offsetof(sockaddr_in, sin_addr);
243  len = sizeof(in_addr);
244  break;
245  case AF_INET6:
246  start = offsetof(sockaddr_in6, sin6_addr);
247  // don't consider more than 64 bits (IPv6)
248  len = 8;
249  break;
250  default:
251  start = 0;
252  len = a.len;
253  break;
254  }
255  return std::memcmp((uint8_t*)a.get()+start,
256  (uint8_t*)b.get()+start, len) < 0;
257  }
258  };
259 private:
260  socklen_t len {0};
261  struct free_delete { void operator()(void* p) { ::free(p); } };
262  std::unique_ptr<sockaddr, free_delete> addr {};
263 
264  void set(const sockaddr* sa, socklen_t length) {
265  if (len != length) {
266  len = length;
267  if (len) addr.reset((sockaddr*)::malloc(len));
268  else addr.reset();
269  }
270  if (len)
271  std::memcpy((uint8_t*)get(), (const uint8_t*)sa, len);
272  }
273 
274 };
275 
276 OPENDHT_PUBLIC bool operator==(const SockAddr& a, const SockAddr& b);
277 
278 }
void setPort(in_port_t p)
Definition: sockaddr.h:167
sa_family_t getFamily() const
Definition: sockaddr.h:121
SockAddr(const sockaddr_storage &ss, socklen_t len)
Definition: sockaddr.h:89
void setFamily(sa_family_t af)
Definition: sockaddr.h:128
SockAddr(const sockaddr *sa, socklen_t length)
Definition: sockaddr.h:68
socklen_t getLength() const
Definition: sockaddr.h:182
Definition: callbacks.h:34
in_port_t getPort() const
Definition: sockaddr.h:153
const sockaddr * get() const
Definition: sockaddr.h:195