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