1 /* 2 * This file is part of OpenTTD. 3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. 4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. 6 */ 7 8 /** @file core/address.h Wrapper for network addresses. */ 9 10 #ifndef NETWORK_CORE_ADDRESS_H 11 #define NETWORK_CORE_ADDRESS_H 12 13 #include "os_abstraction.h" 14 #include "config.h" 15 #include "../../company_type.h" 16 #include "../../string_func.h" 17 #include "../../core/smallmap_type.hpp" 18 19 #include <string> 20 21 class NetworkAddress; 22 typedef std::vector<NetworkAddress> NetworkAddressList; ///< Type for a list of addresses. 23 typedef SmallMap<NetworkAddress, SOCKET> SocketList; ///< Type for a mapping between address and socket. 24 25 /** 26 * Wrapper for (un)resolved network addresses; there's no reason to transform 27 * a numeric IP to a string and then back again to pass it to functions. It 28 * furthermore allows easier delaying of the hostname lookup. 29 */ 30 class NetworkAddress { 31 private: 32 std::string hostname; ///< The hostname 33 int address_length; ///< The length of the resolved address 34 sockaddr_storage address; ///< The resolved address 35 bool resolved; ///< Whether the address has been (tried to be) resolved 36 37 /** 38 * Helper function to resolve something to a socket. 39 * @param runp information about the socket to try not 40 * @return the opened socket or INVALID_SOCKET 41 */ 42 typedef SOCKET (*LoopProc)(addrinfo *runp); 43 44 SOCKET Resolve(int family, int socktype, int flags, SocketList *sockets, LoopProc func); 45 public: 46 /** 47 * Create a network address based on a resolved IP and port. 48 * @param address The IP address with port. 49 * @param address_length The length of the address. 50 */ NetworkAddress(struct sockaddr_storage & address,int address_length)51 NetworkAddress(struct sockaddr_storage &address, int address_length) : 52 address_length(address_length), 53 address(address), 54 resolved(address_length != 0) 55 { 56 } 57 58 /** 59 * Create a network address based on a resolved IP and port. 60 * @param address The IP address with port. 61 * @param address_length The length of the address. 62 */ NetworkAddress(sockaddr * address,int address_length)63 NetworkAddress(sockaddr *address, int address_length) : 64 address_length(address_length), 65 resolved(address_length != 0) 66 { 67 memset(&this->address, 0, sizeof(this->address)); 68 memcpy(&this->address, address, address_length); 69 } 70 71 /** 72 * Create a network address based on a unresolved host and port 73 * @param hostname the unresolved hostname 74 * @param port the port 75 * @param family the address family 76 */ 77 NetworkAddress(std::string_view hostname = "", uint16 port = 0, int family = AF_UNSPEC) : 78 address_length(0), 79 resolved(false) 80 { 81 if (!hostname.empty() && hostname.front() == '[' && hostname.back() == ']') { 82 hostname.remove_prefix(1); 83 hostname.remove_suffix(1); 84 } 85 this->hostname = hostname; 86 87 memset(&this->address, 0, sizeof(this->address)); 88 this->address.ss_family = family; 89 this->SetPort(port); 90 } 91 92 const std::string &GetHostname(); 93 std::string GetAddressAsString(bool with_family = true); 94 const sockaddr_storage *GetAddress(); 95 96 /** 97 * Get the (valid) length of the address. 98 * @return the length 99 */ GetAddressLength()100 int GetAddressLength() 101 { 102 /* Resolve it if we didn't do it already */ 103 if (!this->IsResolved()) this->GetAddress(); 104 return this->address_length; 105 } 106 107 uint16 GetPort() const; 108 void SetPort(uint16 port); 109 110 /** 111 * Check whether the IP address has been resolved already 112 * @return true iff the port has been resolved 113 */ IsResolved()114 bool IsResolved() const 115 { 116 return this->resolved; 117 } 118 119 bool IsFamily(int family); 120 bool IsInNetmask(const std::string &netmask); 121 122 /** 123 * Compare the address of this class with the address of another. 124 * @param address the other address. 125 * @return < 0 if address is less, 0 if equal and > 0 if address is more 126 */ CompareTo(NetworkAddress & address)127 int CompareTo(NetworkAddress &address) 128 { 129 int r = this->GetAddressLength() - address.GetAddressLength(); 130 if (r == 0) r = this->address.ss_family - address.address.ss_family; 131 if (r == 0) r = memcmp(&this->address, &address.address, this->address_length); 132 if (r == 0) r = this->GetPort() - address.GetPort(); 133 return r; 134 } 135 136 /** 137 * Compare the address of this class with the address of another. 138 * @param address the other address. 139 * @return true if both match. 140 */ 141 bool operator == (NetworkAddress &address) 142 { 143 return this->CompareTo(address) == 0; 144 } 145 146 /** 147 * Compare the address of this class with the address of another. 148 * @param address the other address. 149 * @return true if both match. 150 */ 151 bool operator == (NetworkAddress &address) const 152 { 153 return const_cast<NetworkAddress*>(this)->CompareTo(address) == 0; 154 } 155 /** 156 * Compare the address of this class with the address of another. 157 * @param address the other address. 158 * @return true if both do not match. 159 */ 160 bool operator != (NetworkAddress address) const 161 { 162 return const_cast<NetworkAddress*>(this)->CompareTo(address) != 0; 163 } 164 165 /** 166 * Compare the address of this class with the address of another. 167 * @param address the other address. 168 */ 169 bool operator < (NetworkAddress &address) 170 { 171 return this->CompareTo(address) < 0; 172 } 173 174 void Listen(int socktype, SocketList *sockets); 175 176 static const char *SocketTypeAsString(int socktype); 177 static const char *AddressFamilyAsString(int family); 178 static NetworkAddress GetPeerAddress(SOCKET sock); 179 static NetworkAddress GetSockAddress(SOCKET sock); 180 static const std::string GetPeerName(SOCKET sock); 181 }; 182 183 /** 184 * Types of server addresses we know. 185 * 186 * Sorting will prefer entries at the top of this list above ones at the bottom. 187 */ 188 enum ServerAddressType { 189 SERVER_ADDRESS_DIRECT, ///< Server-address is based on an hostname:port. 190 SERVER_ADDRESS_INVITE_CODE, ///< Server-address is based on an invite code. 191 }; 192 193 /** 194 * Address to a game server. 195 * 196 * This generalises addresses which are based on different identifiers. 197 */ 198 class ServerAddress { 199 private: 200 /** 201 * Create a new ServerAddress object. 202 * 203 * Please use ServerAddress::Parse() instead of calling this directly. 204 * 205 * @param type The type of the ServerAdress. 206 * @param connection_string The connection_string that belongs to this ServerAddress type. 207 */ ServerAddress(ServerAddressType type,const std::string & connection_string)208 ServerAddress(ServerAddressType type, const std::string &connection_string) : type(type), connection_string(connection_string) {} 209 210 public: 211 ServerAddressType type; ///< The type of this ServerAddress. 212 std::string connection_string; ///< The connection string for this ServerAddress. 213 214 static ServerAddress Parse(const std::string &connection_string, uint16 default_port, CompanyID *company_id = nullptr); 215 }; 216 217 #endif /* NETWORK_CORE_ADDRESS_H */ 218