OpenTTD Source
12.0-beta2
|
Go to the documentation of this file.
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?)" :
"{}:{}";
107 return !INVALID_SOCKET;
138 return this->
address.ss_family == family;
152 int cidr = this->
address.ss_family == AF_INET ? 32 : 128;
157 auto cidr_separator_location = netmask.find(
'/');
158 if (cidr_separator_location != std::string::npos) {
159 int tmp_cidr = atoi(netmask.substr(cidr_separator_location + 1).c_str());
162 if (tmp_cidr > 0 && tmp_cidr < cidr) cidr = tmp_cidr;
165 mask_address =
NetworkAddress(netmask.substr(0, cidr_separator_location), 0, this->address.ss_family);
174 switch (this->
address.ss_family) {
176 ip = (uint32*)&((
struct sockaddr_in*)&this->
address)->sin_addr.s_addr;
177 mask = (uint32*)&((
struct sockaddr_in*)&mask_address.
address)->sin_addr.s_addr;
181 ip = (uint32*)&((
struct sockaddr_in6*)&this->
address)->sin6_addr;
182 mask = (uint32*)&((
struct sockaddr_in6*)&mask_address.
address)->sin6_addr;
190 uint32 msk = cidr >= 32 ? (uint32)-1 : htonl(-(1 << (32 - cidr)));
191 if ((*mask++ & msk) != (*ip++ & msk))
return false;
211 struct addrinfo hints;
212 memset(&hints, 0,
sizeof (hints));
213 hints.ai_family = family;
214 hints.ai_flags = flags;
215 hints.ai_socktype = socktype;
221 bool reset_hostname =
false;
225 if (this->
hostname.empty() && this->address_length == 0 && this->GetPort() == 0) {
226 reset_hostname =
true;
227 int fam = this->
address.ss_family;
228 if (fam == AF_UNSPEC) fam = family;
229 this->
hostname = fam == AF_INET ?
"0.0.0.0" :
"::";
232 static bool _resolve_timeout_error_message_shown =
false;
233 auto start = std::chrono::steady_clock::now();
234 int e = getaddrinfo(this->
hostname.empty() ?
nullptr : this->hostname.c_str(), port_name, &hints, &ai);
235 auto end = std::chrono::steady_clock::now();
236 std::chrono::seconds duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
237 if (!_resolve_timeout_error_message_shown && duration >= std::chrono::seconds(5)) {
238 Debug(net, 0,
"getaddrinfo for hostname \"{}\", port {}, address family {} and socket type {} took {} seconds",
240 Debug(net, 0,
" this is likely an issue in the DNS name resolver's configuration causing it to time out");
241 _resolve_timeout_error_message_shown =
true;
245 if (reset_hostname) this->
hostname.clear();
249 Debug(net, 0,
"getaddrinfo for hostname \"{}\", port {}, address family {} and socket type {} failed: {}",
252 return INVALID_SOCKET;
255 SOCKET sock = INVALID_SOCKET;
256 for (
struct addrinfo *runp = ai; runp !=
nullptr; runp = runp->ai_next) {
260 if (sockets !=
nullptr) {
265 if (sock == INVALID_SOCKET)
continue;
267 if (sockets ==
nullptr) {
269 assert(
sizeof(this->
address) >= runp->ai_addrlen);
270 memcpy(&this->
address, runp->ai_addr, runp->ai_addrlen);
271 #ifdef __EMSCRIPTEN__
278 if (this->
address.ss_family == AF_INET) {
279 sockaddr_in *address_ipv4 = (sockaddr_in *)&this->
address;
280 memset(address_ipv4->sin_zero, 0,
sizeof(address_ipv4->sin_zero));
287 (*sockets)[addr] = sock;
288 sock = INVALID_SOCKET;
304 SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
305 if (sock == INVALID_SOCKET) {
309 return INVALID_SOCKET;
312 if (runp->ai_socktype == SOCK_STREAM && !
SetNoDelay(sock)) {
322 if (runp->ai_family == AF_INET6 &&
323 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (
const char*)&on,
sizeof(on)) == -1) {
328 if (bind(sock, runp->ai_addr, (
int)runp->ai_addrlen) != 0) {
331 return INVALID_SOCKET;
334 if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
337 return INVALID_SOCKET;
346 Debug(net, 3,
"Listening on {}", address);
357 assert(sockets !=
nullptr);
363 this->hostname.empty() && this->GetPort() == 0) {
380 case SOCK_STREAM:
return "tcp";
381 case SOCK_DGRAM:
return "udp";
382 default:
return "unsupported";
395 case AF_UNSPEC:
return "either IPv4 or IPv6";
396 case AF_INET:
return "IPv4";
397 case AF_INET6:
return "IPv6";
398 default:
return "unsupported";
409 sockaddr_storage addr = {};
410 socklen_t addr_len =
sizeof(addr);
411 if (getpeername(sock, (sockaddr *)&addr, &addr_len) != 0) {
425 sockaddr_storage addr = {};
426 socklen_t addr_len =
sizeof(addr);
427 if (getsockname(sock, (sockaddr *)&addr, &addr_len) != 0) {
461 uint16 port = default_port;
std::string hostname
The hostname.
const sockaddr_storage * GetAddress()
Get the address in its internal representation.
bool SetReusePort(SOCKET d)
Try to set the socket to reuse ports.
int GetAddressLength()
Get the (valid) length of the address.
void SetPort(uint16 port)
Set the port.
SOCKET Resolve(int family, int socktype, int flags, SocketList *sockets, LoopProc func)
Resolve this address into a socket.
bool resolved
Whether the address has been (tried to be) resolved.
bool IsInNetmask(const std::string &netmask)
Checks whether this IP address is contained by the given netmask.
static SOCKET ResolveLoopProc(addrinfo *runp)
Helper function to resolve without opening a socket.
Owner
Enum for all companies/owners.
static ServerAddress Parse(const std::string &connection_string, uint16 default_port, CompanyID *company_id=nullptr)
Convert a string containing either "hostname", "hostname:port" or invite code to a ServerAddress,...
static NetworkAddress GetPeerAddress(SOCKET sock)
Get the peer address of a socket as NetworkAddress.
static NetworkAddress GetSockAddress(SOCKET sock)
Get the local address of a socket as NetworkAddress.
static const std::string GetPeerName(SOCKET sock)
Get the peer name of a socket in string format.
std::string FS2OTTD(const std::wstring &name)
Convert to OpenTTD's encoding from a wide string.
static NetworkError GetLast()
Get the last network error.
@ SERVER_ADDRESS_DIRECT
Server-address is based on an hostname:port.
static SOCKET ListenLoopProc(addrinfo *runp)
Helper function to resolve a listening.
bool StrStartsWith(const std::string_view str, const std::string_view prefix)
Check whether the given string starts with the given prefix.
uint16 GetPort() const
Get the port.
int address_length
The length of the resolved address.
std::string_view ParseFullConnectionString(const std::string &connection_string, uint16 &port, CompanyID *company_id)
Converts a string to ip/port/company Format: IP:port::company.
NetworkAddress(struct sockaddr_storage &address, int address_length)
Create a network address based on a resolved IP and port.
std::string GetAddressAsString(bool with_family=true)
Get the address as a string, e.g.
std::string_view ParseCompanyFromConnectionString(const std::string &connection_string, CompanyID *company_id)
Parse the company part ("#company" postfix) of a connecting string.
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
bool IsResolved() const
Check whether the IP address has been resolved already.
const std::string & GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
static const char * SocketTypeAsString(int socktype)
Convert the socket type into a string.
@ SERVER_ADDRESS_INVITE_CODE
Server-address is based on an invite code.
#define Debug(name, level, format_string,...)
Ouptut a line of debugging information.
bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
bool IsFamily(int family)
Checks of this address is of the given family.
static const uint NETWORK_HOSTNAME_LENGTH
The maximum length of the host name, in bytes including '\0'.
static const char * AddressFamilyAsString(int family)
Convert the address family into a string.
std::string connection_string
The connection string for this ServerAddress.
#define lastof(x)
Get the last element of an fixed size array.
bool SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
void Listen(int socktype, SocketList *sockets)
Make the given socket listen.
Address to a game server.
ServerAddress(ServerAddressType type, const std::string &connection_string)
Create a new ServerAddress object.
static const char * GetAddressFormatString(uint16 family, bool with_family)
Helper to get the formatting string of an address for a given family.
sockaddr_storage address
The resolved address.
bool Contains(const T &key) const
Tests whether a key is assigned in this map.