My Project 2.4.4
C++ Distributed Hash Table
Loading...
Searching...
No Matches
sockaddr.h
1/*
2 * Copyright (C) 2014-2022 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#include <arpa/inet.h>
27#ifdef __ANDROID__
28typedef uint16_t in_port_t;
29#endif
30#else
31#include <iso646.h>
32#include <stdint.h>
33#include <winsock2.h>
34#include <ws2def.h>
35#include <ws2tcpip.h>
36typedef uint16_t sa_family_t;
37typedef uint16_t in_port_t;
38#endif
39
40#include <string>
41#include <memory>
42#include <vector>
43#include <stdexcept>
44#include <stdlib.h>
45
46#include <cstring>
47#include <cstddef>
48
49namespace dht {
50
51OPENDHT_PUBLIC std::string print_addr(const sockaddr* sa, socklen_t slen);
52OPENDHT_PUBLIC std::string print_addr(const sockaddr_storage& ss, socklen_t sslen);
53
57class OPENDHT_PUBLIC SockAddr {
58public:
59 SockAddr() {}
60 SockAddr(const SockAddr& o) {
61 set(o.get(), o.getLength());
62 }
63 SockAddr(SockAddr&& o) noexcept : addr(std::move(o.addr)), len(o.len) {
64 o.len = 0;
65 }
66
70 SockAddr(const sockaddr* sa, socklen_t length) {
71 if (length > static_cast<socklen_t>(sizeof(sockaddr_storage)))
72 throw std::runtime_error("Socket address length is too large");
73 set(sa, length);
74 }
75 SockAddr(const sockaddr* sa) {
76 socklen_t len = 0;
77 if (sa) {
78 if (sa->sa_family == AF_INET)
79 len = sizeof(sockaddr_in);
80 else if(sa->sa_family == AF_INET6)
81 len = sizeof(sockaddr_in6);
82 else
83 throw std::runtime_error("Unknown address family");
84 }
85 set(sa, len);
86 }
87
91 SockAddr(const sockaddr_storage& ss, socklen_t len) : SockAddr((const sockaddr*)&ss, len) {}
92
93 static std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {});
94
95 bool operator<(const SockAddr& o) const {
96 if (len != o.len)
97 return len < o.len;
98 return std::memcmp((const uint8_t*)get(), (const uint8_t*)o.get(), len) < 0;
99 }
100
101 bool equals(const SockAddr& o) const {
102 return len == o.len
103 && std::memcmp((const uint8_t*)get(), (const uint8_t*)o.get(), len) == 0;
104 }
105 SockAddr& operator=(const SockAddr& o) {
106 set(o.get(), o.getLength());
107 return *this;
108 }
109 SockAddr& operator=(SockAddr&& o) {
110 len = o.len;
111 o.len = 0;
112 addr = std::move(o.addr);
113 return *this;
114 }
115
116 std::string toString() const {
117 return print_addr(get(), getLength());
118 }
119
123 sa_family_t getFamily() const { return len ? addr->sa_family : AF_UNSPEC; }
124
130 void setFamily(sa_family_t af) {
131 socklen_t new_length;
132 switch(af) {
133 case AF_INET:
134 new_length = sizeof(sockaddr_in);
135 break;
136 case AF_INET6:
137 new_length = sizeof(sockaddr_in6);
138 break;
139 default:
140 new_length = 0;
141 }
142 if (new_length != len) {
143 len = new_length;
144 if (len) addr.reset((sockaddr*)::calloc(len, 1));
145 else addr.reset();
146 }
147 if (len)
148 addr->sa_family = af;
149 }
150
154 void setAny() {
155 auto family = getFamily();
156 switch(family) {
157 case AF_INET:
158 getIPv4().sin_addr.s_addr = htonl(INADDR_ANY);
159 break;
160 case AF_INET6:
161 getIPv6().sin6_addr = in6addr_any;
162 break;
163 }
164 }
165
170 in_port_t getPort() const {
171 switch(getFamily()) {
172 case AF_INET:
173 return ntohs(getIPv4().sin_port);
174 case AF_INET6:
175 return ntohs(getIPv6().sin6_port);
176 default:
177 return 0;
178 }
179 }
184 void setPort(in_port_t p) {
185 switch(getFamily()) {
186 case AF_INET:
187 getIPv4().sin_port = htons(p);
188 break;
189 case AF_INET6:
190 getIPv6().sin6_port = htons(p);
191 break;
192 }
193 }
194
199 void setAddress(const char* address);
200
205 socklen_t getLength() const { return len; }
206
210 explicit operator bool() const noexcept {
211 return len;
212 }
213
218 const sockaddr* get() const { return addr.get(); }
219
224 sockaddr* get() { return addr.get(); }
225
226 inline const sockaddr_in& getIPv4() const {
227 return *reinterpret_cast<const sockaddr_in*>(get());
228 }
229 inline const sockaddr_in6& getIPv6() const {
230 return *reinterpret_cast<const sockaddr_in6*>(get());
231 }
232 inline sockaddr_in& getIPv4() {
233 return *reinterpret_cast<sockaddr_in*>(get());
234 }
235 inline sockaddr_in6& getIPv6() {
236 return *reinterpret_cast<sockaddr_in6*>(get());
237 }
238
242 bool isLoopback() const;
243
247 bool isPrivate() const;
248
249 bool isUnspecified() const;
250
251 bool isMappedIPv4() const;
252 SockAddr getMappedIPv4();
253 SockAddr getMappedIPv6();
254
259 struct ipCmp {
260 bool operator()(const SockAddr& a, const SockAddr& b) const {
261 if (a.len != b.len)
262 return a.len < b.len;
263 socklen_t start, len;
264 switch(a.getFamily()) {
265 case AF_INET:
266 start = offsetof(sockaddr_in, sin_addr);
267 len = sizeof(in_addr);
268 break;
269 case AF_INET6:
270 start = offsetof(sockaddr_in6, sin6_addr);
271 // don't consider more than 64 bits (IPv6)
272 len = 8;
273 break;
274 default:
275 start = 0;
276 len = a.len;
277 break;
278 }
279 return std::memcmp((uint8_t*)a.get()+start,
280 (uint8_t*)b.get()+start, len) < 0;
281 }
282 };
283private:
284 struct free_delete { void operator()(void* p) { ::free(p); } };
285 std::unique_ptr<sockaddr, free_delete> addr {};
286 socklen_t len {0};
287
288 void set(const sockaddr* sa, socklen_t length) {
289 if (len != length) {
290 len = length;
291 if (len) addr.reset((sockaddr*)::malloc(len));
292 else addr.reset();
293 }
294 if (len)
295 std::memcpy((uint8_t*)get(), (const uint8_t*)sa, len);
296 }
297
298};
299
300OPENDHT_PUBLIC bool operator==(const SockAddr& a, const SockAddr& b);
301
302}
SockAddr(const sockaddr *sa, socklen_t length)
Definition: sockaddr.h:70
SockAddr(const sockaddr_storage &ss, socklen_t len)
Definition: sockaddr.h:91
void setFamily(sa_family_t af)
Definition: sockaddr.h:130
void setPort(in_port_t p)
Definition: sockaddr.h:184
const sockaddr * get() const
Definition: sockaddr.h:218
sockaddr * get()
Definition: sockaddr.h:224
socklen_t getLength() const
Definition: sockaddr.h:205
void setAddress(const char *address)
void setAny()
Definition: sockaddr.h:154
sa_family_t getFamily() const
Definition: sockaddr.h:123
bool isPrivate() const
bool isLoopback() const
in_port_t getPort() const
Definition: sockaddr.h:170
Definition: callbacks.h:35