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 return ntohs(getIPv4().sin_port);
180 return ntohs(getIPv6().sin6_port);
192 getIPv4().sin_port = htons(p);
195 getIPv6().sin6_port = htons(p);
215 explicit operator bool() const noexcept {
223 const sockaddr*
get()
const {
return addr.get(); }
229 sockaddr*
get() {
return addr.get(); }
231 inline const sockaddr_in& getIPv4()
const {
232 return *
reinterpret_cast<const sockaddr_in*
>(get());
234 inline const sockaddr_in6& getIPv6()
const {
235 return *
reinterpret_cast<const sockaddr_in6*
>(get());
237 inline sockaddr_in& getIPv4() {
238 return *
reinterpret_cast<sockaddr_in*
>(get());
240 inline sockaddr_in6& getIPv6() {
241 return *
reinterpret_cast<sockaddr_in6*
>(get());
250 return addr.release();
263 bool isUnspecified()
const;
265 bool isMappedIPv4()
const;
266 SockAddr getMappedIPv4();
267 SockAddr getMappedIPv6();
274 bool operator()(
const SockAddr& a,
const SockAddr& b)
const {
276 return a.len < b.len;
277 socklen_t start, len;
280 start = offsetof(sockaddr_in, sin_addr);
281 len =
sizeof(in_addr);
284 start = offsetof(sockaddr_in6, sin6_addr);
293 return std::memcmp((uint8_t*)a.
get()+start,
294 (uint8_t*)b.
get()+start, len) < 0;
297 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const SockAddr& h) {
303 struct free_delete {
void operator()(
void* p) { ::free(p); } };
304 std::unique_ptr<sockaddr, free_delete> addr {};
307 void set(
const sockaddr* sa, socklen_t length) {
310 if (len) addr.reset((sockaddr*)::malloc(len));
314 std::memcpy((uint8_t*)get(), (
const uint8_t*)sa, len);