1 /* 2 * Copyright (C) 2004-2020 by the Widelands Development Team 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20 #ifndef WL_NETWORK_NETWORK_H 21 #define WL_NETWORK_NETWORK_H 22 23 #include <functional> 24 25 #include <boost/asio.hpp> 26 #include <boost/lexical_cast.hpp> 27 28 #include "base/wexception.h" 29 #include "io/streamread.h" 30 #include "io/streamwrite.h" 31 #include "logic/cmd_queue.h" 32 #include "network/network_protocol.h" 33 34 constexpr size_t kNetworkBufferSize = 512; 35 36 /** 37 * Simple structure to hold the IP address and port of a server. 38 * This structure must not contain a hostname but only IP addresses. 39 */ 40 struct NetAddress { 41 /** 42 * Tries to resolve the given hostname to an IPv4 address. 43 * \param[out] addr A NetAddress structure to write the result to, 44 * if resolution succeeds. 45 * \param hostname The name of the host. 46 * \param port The port on the host. 47 * \return \c True if the resolution succeeded, \c false otherwise. 48 */ 49 static bool resolve_to_v4(NetAddress* addr, const std::string& hostname, uint16_t port); 50 51 /** 52 * Tries to resolve the given hostname to an IPv6 address. 53 * \param[out] addr A NetAddress structure to write the result to, 54 * if resolution succeeds. 55 * \param hostname The name of the host. 56 * \param port The port on the host. 57 * \return \c True if the resolution succeeded, \c false otherwise. 58 */ 59 static bool resolve_to_v6(NetAddress* addr, const std::string& hostname, uint16_t port); 60 61 /** 62 * Parses the given string to an IP address. 63 * \param[out] addr A NetAddress structure to write the result to, 64 * if parsing succeeds. 65 * \param ip An IP address as string. 66 * \param port The port on the host. 67 * \return \c True if the parsing succeeded, \c false otherwise. 68 */ 69 static bool parse_ip(NetAddress* addr, const std::string& ip, uint16_t port); 70 71 /** 72 * Returns whether the stored IP is in IPv6 format. 73 * @return \c true if the stored IP is in IPv6 format, \c false otherwise. 74 * If it isn't an IPv6 address, it is an IPv4 address. 75 */ 76 bool is_ipv6() const; 77 78 /** 79 * Returns whether valid IP address and port are stored. 80 * @return \c true if valid, \c false otherwise. 81 */ 82 bool is_valid() const; 83 84 boost::asio::ip::address ip; 85 uint16_t port; 86 }; 87 88 using SyncReportCallback = std::function<void()>; 89 90 /** 91 * This non-gamelogic command is used by \ref GameHost and \ref GameClient 92 * to schedule taking a synchronization hash. 93 */ 94 struct CmdNetCheckSync : public Widelands::Command { 95 CmdNetCheckSync(uint32_t dt, SyncReportCallback); 96 97 void execute(Widelands::Game&) override; 98 idCmdNetCheckSync99 Widelands::QueueCommandTypes id() const override { 100 return Widelands::QueueCommandTypes::kNetCheckSync; 101 } 102 103 private: 104 SyncReportCallback callback_; 105 }; 106 107 /** 108 * Keeping track of network time: This class answers the question of how 109 * far the local simulation time should proceed, given the history of network 110 * time messages forwarded to the \ref receive() method. 111 * 112 * In general, the time progresses as fast as given by the speed, but we 113 * introduce some elasticity to catch up with the network time if necessary, 114 * and we never advance simulation past the received network time. 115 */ 116 class NetworkTime { 117 public: 118 NetworkTime(); 119 120 void reset(int32_t ntime); 121 void fastforward(); 122 123 void think(uint32_t speed); 124 int32_t time() const; 125 int32_t networktime() const; 126 void receive(int32_t ntime); 127 128 private: 129 int32_t networktime_; 130 int32_t time_; 131 132 uint32_t lastframe_; 133 134 /// This is an attempt to measure how far behind the network time we are. 135 uint32_t latency_; 136 }; 137 138 /** 139 * Buffered StreamWrite object for assembling a packet that will be 140 * sent over the network. 141 */ 142 struct SendPacket : public StreamWrite { 143 SendPacket(); 144 145 void reset(); 146 147 void data(void const* data, size_t size) override; 148 149 size_t get_size() const; 150 151 uint8_t* get_data() const; 152 153 private: 154 // First two bytes are overwritten on call to get_data() 155 mutable std::vector<uint8_t> buffer; 156 }; 157 158 /** 159 * One packet, as received from the network. 160 */ 161 struct RecvPacket : public StreamRead { 162 public: 163 size_t data(void* data, size_t bufsize) override; 164 bool end_of_file() const override; 165 166 private: 167 friend class BufferedConnection; 168 std::vector<uint8_t> buffer; 169 size_t index_ = 0U; 170 }; 171 172 struct FilePart { 173 char part[NETFILEPARTSIZE]; 174 }; 175 176 struct NetTransferFile { NetTransferFileNetTransferFile177 NetTransferFile() : bytes(0), filename(""), md5sum("") { 178 } 179 ~NetTransferFile() = default; 180 181 uint32_t bytes; 182 std::string filename; 183 std::string md5sum; 184 std::vector<FilePart> parts; 185 }; 186 187 /** 188 * This exception is used internally during protocol handling to indicate 189 * that the connection should be terminated with a reasonable error message. 190 * 191 * If the network handler catches a different exception from std::exception, 192 * it assumes that it is due to malformed data sent by the server. 193 */ 194 struct DisconnectException : public std::exception { 195 explicit DisconnectException(const char* fmt, ...) PRINTF_FORMAT(2, 3); 196 197 const char* what() const noexcept override; 198 199 private: 200 std::string what_; 201 }; 202 203 /** 204 * This exception is used internally during protocol handling to indicate that the connection 205 * should be terminated because an unexpected message got received that is disallowed by the 206 * protocol. 207 */ 208 struct ProtocolException : public std::exception { ProtocolExceptionProtocolException209 explicit ProtocolException(uint8_t code) 210 : what_(boost::lexical_cast<std::string>(static_cast<unsigned int>(code))) { 211 } 212 213 /// \returns the command number of the received message whatProtocolException214 const char* what() const noexcept override { 215 return what_.c_str(); 216 } 217 218 private: 219 const std::string what_; 220 }; 221 222 /** 223 * The priorities for sending data over the network when using a BufferedConnection. 224 * Data with low priority values is send first even when data with high priority values 225 * have been passed to a BufferedConnection first 226 */ 227 // The values assigned to the entries are arbitrary, only their order is important 228 // No "enum class" on purpose since this has to be interpreted as ints (I need a known ordering) 229 enum NetPriority : uint8_t { kPing = 10, kNormal = 50, kFiletransfer = 100 }; 230 231 #endif // end of include guard: WL_NETWORK_NETWORK_H 232