55OPENDHT_PUBLIC
void print_addr(std::ostream& os,
const sockaddr* sa, socklen_t slen);
56OPENDHT_PUBLIC std::string print_addr(
const sockaddr* sa, socklen_t slen);
57OPENDHT_PUBLIC std::string print_addr(
const sockaddr_storage& ss, socklen_t sslen);
62class OPENDHT_PUBLIC SockAddr {
65 SockAddr(
const SockAddr& o) {
68 SockAddr(SockAddr&& o) noexcept : addr(std::move(o.addr)), len(o.len) {
75 SockAddr(
const sockaddr* sa, socklen_t length) {
76 if (length >
static_cast<socklen_t
>(
sizeof(sockaddr_storage)))
77 throw std::runtime_error(
"Socket address length is too large");
83 if (sa->sa_family == AF_INET)
84 len =
sizeof(sockaddr_in);
85 else if(sa->sa_family == AF_INET6)
86 len =
sizeof(sockaddr_in6);
88 throw std::runtime_error(
"Unknown address family");
96 SockAddr(
const sockaddr_storage& ss, socklen_t len) : SockAddr((const sockaddr*)&ss, len) {}
98 static std::vector<SockAddr> resolve(
const std::string& host,
const std::string& service = {});
100 bool operator<(
const SockAddr& o)
const {
103 return std::memcmp((
const uint8_t*)get(), (
const uint8_t*)o.get(), len) < 0;
106 bool equals(
const SockAddr& o)
const {
108 && std::memcmp((
const uint8_t*)get(), (
const uint8_t*)o.get(), len) == 0;
110 SockAddr& operator=(
const SockAddr& o) {
111 set(o.get(), o.getLength());
114 SockAddr& operator=(SockAddr&& o) {
117 addr = std::move(o.addr);
121 std::string toString()
const {
122 return print_addr(get(), getLength());
128 sa_family_t
getFamily()
const {
return len ? addr->sa_family : AF_UNSPEC; }
136 socklen_t new_length;
139 new_length =
sizeof(sockaddr_in);
142 new_length =
sizeof(sockaddr_in6);
147 if (new_length != len) {
149 if (len) addr.reset((sockaddr*)::calloc(len, 1));
153 addr->sa_family = af;
163 getIPv4().sin_addr.s_addr = htonl(INADDR_ANY);
166 getIPv6().sin6_addr = in6addr_any;
178 getIPv4().sin_addr.s_addr = htonl(INADDR_LOOPBACK);
181 getIPv6().sin6_addr = in6addr_loopback;
193 return ntohs(getIPv4().sin_port);
195 return ntohs(getIPv6().sin6_port);
207 getIPv4().sin_port = htons(p);
210 getIPv6().sin6_port = htons(p);
230 explicit operator bool() const noexcept {
238 const sockaddr*
get()
const {
return addr.get(); }
244 sockaddr*
get() {
return addr.get(); }
246 inline const sockaddr_in& getIPv4()
const {
247 return *
reinterpret_cast<const sockaddr_in*
>(get());
249 inline const sockaddr_in6& getIPv6()
const {
250 return *
reinterpret_cast<const sockaddr_in6*
>(get());
252 inline sockaddr_in& getIPv4() {
253 return *
reinterpret_cast<sockaddr_in*
>(get());
255 inline sockaddr_in6& getIPv6() {
256 return *
reinterpret_cast<sockaddr_in6*
>(get());
265 return addr.release();
278 bool isUnspecified()
const;
280 bool isMappedIPv4()
const;
281 SockAddr getMappedIPv4();
282 SockAddr getMappedIPv6();
289 bool operator()(
const SockAddr& a,
const SockAddr& b)
const {
291 return a.len < b.len;
292 socklen_t start, len;
295 start = offsetof(sockaddr_in, sin_addr);
296 len =
sizeof(in_addr);
299 start = offsetof(sockaddr_in6, sin6_addr);
308 return std::memcmp((uint8_t*)a.
get()+start,
309 (uint8_t*)b.
get()+start, len) < 0;
312 friend std::ostream& operator<< (std::ostream& s,
const SockAddr& h) {
318 struct free_delete {
void operator()(
void* p) { ::free(p); } };
319 std::unique_ptr<sockaddr, free_delete> addr {};
322 void set(
const sockaddr* sa, socklen_t length) {
325 if (len) addr.reset((sockaddr*)::malloc(len));
329 std::memcpy((uint8_t*)get(), (
const uint8_t*)sa, len);