10 #include "../../stdafx.h"
13 #include "../network_internal.h"
14 #include "../../debug.h"
16 #include "../../safeguards.h"
25 if (this->
hostname.empty() && this->address.ss_family != AF_UNSPEC) {
28 getnameinfo((
struct sockaddr *)&this->
address, this->
address_length, buffer,
sizeof(buffer),
nullptr, 0, NI_NUMERICHOST);
40 switch (this->
address.ss_family) {
43 return ntohs(((
const struct sockaddr_in *)&this->
address)->sin_port);
46 return ntohs(((
const struct sockaddr_in6 *)&this->address)->sin6_port);
59 switch (this->
address.ss_family) {
62 ((
struct sockaddr_in*)&this->
address)->sin_port = htons(port);
66 ((
struct sockaddr_in6*)&this->
address)->sin6_port = htons(port);
83 case AF_INET:
return with_family ?
"{}:{} (IPv4)" :
"{}:{}";
84 case AF_INET6:
return with_family ?
"[{}]:{} (IPv6)" :
"[{}]:{}";
85 default:
return with_family ?
"{}:{} (IPv?)" :
"{}:{}";
106 return !INVALID_SOCKET;
137 return this->
address.ss_family == family;
151 int cidr = this->
address.ss_family == AF_INET ? 32 : 128;
156 auto cidr_separator_location = netmask.find(
'/');
157 if (cidr_separator_location != std::string::npos) {
158 int tmp_cidr = atoi(netmask.substr(cidr_separator_location + 1).c_str());
161 if (tmp_cidr > 0 && tmp_cidr < cidr) cidr = tmp_cidr;
164 mask_address =
NetworkAddress(netmask.substr(0, cidr_separator_location), 0, this->address.ss_family);
173 switch (this->
address.ss_family) {
175 ip = (uint32_t*)&((
struct sockaddr_in*)&this->
address)->sin_addr.s_addr;
176 mask = (uint32_t*)&((
struct sockaddr_in*)&mask_address.
address)->sin_addr.s_addr;
180 ip = (uint32_t*)&((
struct sockaddr_in6*)&this->
address)->sin6_addr;
181 mask = (uint32_t*)&((
struct sockaddr_in6*)&mask_address.
address)->sin6_addr;
189 uint32_t msk = cidr >= 32 ? (uint32_t)-1 : htonl(-(1 << (32 - cidr)));
190 if ((*mask++ & msk) != (*ip++ & msk))
return false;
210 struct addrinfo hints;
211 memset(&hints, 0,
sizeof (hints));
212 hints.ai_family = family;
213 hints.ai_flags = flags;
214 hints.ai_socktype = socktype;
217 std::string port_name = std::to_string(this->
GetPort());
219 bool reset_hostname =
false;
223 if (this->
hostname.empty() && this->address_length == 0 && this->GetPort() == 0) {
224 reset_hostname =
true;
225 int fam = this->
address.ss_family;
226 if (fam == AF_UNSPEC) fam = family;
227 this->
hostname = fam == AF_INET ?
"0.0.0.0" :
"::";
230 static bool _resolve_timeout_error_message_shown =
false;
231 auto start = std::chrono::steady_clock::now();
232 int e = getaddrinfo(this->
hostname.empty() ?
nullptr : this->hostname.c_str(), port_name.c_str(), &hints, &ai);
233 auto end = std::chrono::steady_clock::now();
234 std::chrono::seconds duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
235 if (!_resolve_timeout_error_message_shown && duration >= std::chrono::seconds(5)) {
236 Debug(net, 0,
"getaddrinfo for hostname \"{}\", port {}, address family {} and socket type {} took {} seconds",
238 Debug(net, 0,
" this is likely an issue in the DNS name resolver's configuration causing it to time out");
239 _resolve_timeout_error_message_shown =
true;
243 if (reset_hostname) this->
hostname.clear();
247 Debug(net, 0,
"getaddrinfo for hostname \"{}\", port {}, address family {} and socket type {} failed: {}",
250 return INVALID_SOCKET;
253 SOCKET sock = INVALID_SOCKET;
254 for (
struct addrinfo *runp = ai; runp !=
nullptr; runp = runp->ai_next) {
258 if (sockets !=
nullptr) {
260 if (std::any_of(sockets->begin(), sockets->end(), [&
address](
const auto &p) { return p.second == address; }))
continue;
263 if (sock == INVALID_SOCKET)
continue;
265 if (sockets ==
nullptr) {
267 assert(
sizeof(this->
address) >= runp->ai_addrlen);
268 memcpy(&this->
address, runp->ai_addr, runp->ai_addrlen);
269 #ifdef __EMSCRIPTEN__
276 if (this->
address.ss_family == AF_INET) {
277 sockaddr_in *address_ipv4 = (sockaddr_in *)&this->
address;
278 memset(address_ipv4->sin_zero, 0,
sizeof(address_ipv4->sin_zero));
285 (*sockets)[sock] = addr;
286 sock = INVALID_SOCKET;
302 SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
303 if (sock == INVALID_SOCKET) {
307 return INVALID_SOCKET;
310 if (runp->ai_socktype == SOCK_STREAM && !
SetNoDelay(sock)) {
319 if (runp->ai_family == AF_INET6 &&
320 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (
const char*)&on,
sizeof(on)) == -1) {
324 if (bind(sock, runp->ai_addr, (
int)runp->ai_addrlen) != 0) {
327 return INVALID_SOCKET;
330 if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
333 return INVALID_SOCKET;
342 Debug(net, 3,
"Listening on {}", address);
353 assert(sockets !=
nullptr);
359 this->hostname.empty() && this->GetPort() == 0) {
376 case SOCK_STREAM:
return "tcp";
377 case SOCK_DGRAM:
return "udp";
378 default:
return "unsupported";
391 case AF_UNSPEC:
return "either IPv4 or IPv6";
392 case AF_INET:
return "IPv4";
393 case AF_INET6:
return "IPv6";
394 default:
return "unsupported";
405 sockaddr_storage addr = {};
406 socklen_t addr_len =
sizeof(addr);
407 if (getpeername(sock, (sockaddr *)&addr, &addr_len) != 0) {
421 sockaddr_storage addr = {};
422 socklen_t addr_len =
sizeof(addr);
423 if (getsockname(sock, (sockaddr *)&addr, &addr_len) != 0) {
457 uint16_t port = default_port;