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_INTERNET_GAMING_H 21 #define WL_NETWORK_INTERNET_GAMING_H 22 23 #include <memory> 24 25 #include "chat/chat.h" 26 #include "network/netclient.h" 27 #include "network/network.h" 28 29 /// A simple network client struct 30 struct InternetClient { 31 std::string name; 32 std::string build_id; 33 std::string game; 34 std::string type; 35 }; 36 37 /// A simple network game struct 38 struct InternetGame { 39 std::string name; 40 std::string build_id; 41 std::string connectable; 42 }; 43 44 /** 45 * The InternetGaming struct. 46 */ 47 struct InternetGaming : public ChatProvider { 48 49 /// The only instance of InternetGaming -> the constructor is private by purpose! 50 static InternetGaming& ref(); 51 52 void reset(); 53 54 // Login and logout 55 56 void initialize_connection(); 57 58 /** 59 * Try to login on the metaserver. 60 * @param nick The preferred username. Another username might be chosen by the metaserver if 61 * the requested one is already in use. 62 * @param authenticator If \c registered is \c true, this is the password. Otherwise, it is some 63 * unique 64 * id the server can use to identify the user. 65 * @param metaserver The hostname of the metaserver. 66 * @param port The port number of the metaserver. 67 * @return Whether the login was successful. 68 */ 69 bool login(const std::string& nick, 70 const std::string& authenticator, 71 bool registered, 72 const std::string& metaserver, 73 uint32_t port); 74 bool relogin(); 75 void logout(const std::string& msgcode = "CONNECTION_CLOSED"); 76 77 /** 78 * Connects to the metaserver and checks the password without logging in. 79 * 80 * Note that the user might be logged in with another username and as unregistered 81 * if the user account is already in use by another client. 82 * @warning Resets the current connection. 83 * @param nick The username. 84 * @param pwd The password. 85 * @param metaserver The hostname of the metaserver. 86 * @param port The port number of the metaserver. 87 * @return Whether the password was valid. 88 */ 89 bool check_password(const std::string& nick, 90 const std::string& pwd, 91 const std::string& metaserver, 92 uint32_t port); 93 94 /// \returns whether the client is logged in logged_inInternetGaming95 bool logged_in() { 96 return (state_ == LOBBY) || (state_ == CONNECTING) || (state_ == IN_GAME); 97 } errorInternetGaming98 bool error() { 99 return (state_ == COMMUNICATION_ERROR); 100 } set_errorInternetGaming101 void set_error() { 102 state_ = COMMUNICATION_ERROR; 103 gameupdate_ = true; 104 clientupdate_ = true; 105 } 106 107 void handle_metaserver_communication(bool relogin_on_error = true); 108 109 // Game specific functions 110 /** 111 * Returns a pair containing up to two NetAddress'es of the game host to connect to. 112 * Contains two addresses when the host supports IPv4 and IPv6, one address when the host 113 * only supports one of the protocols, no addresses when no join-request was sent to 114 * the metaserver. "No address" means a default constructed address. 115 * Also returns the IPs of the relay server when trying to host a game. 116 * Use NetAddress::is_valid() to check whether a NetAddress has been default constructed. 117 * @return The addresses. 118 */ 119 const std::pair<NetAddress, NetAddress>& ips(); 120 121 /** 122 * Blocks for some time until either the ips() method is able to return the IPs of the relay 123 * or an error occurred or the timeout is met. 124 * @return \c True iff ips() can return something. 125 */ 126 bool wait_for_ips(); 127 128 /** 129 * Returns the password required to connect to the relay server as host. 130 */ 131 const std::string relay_password(); 132 133 void join_game(const std::string& gamename); 134 void open_game(); 135 void set_game_playing(); 136 void set_game_done(); 137 138 // Informative functions for lobby 139 bool update_for_games(); 140 const std::vector<InternetGame>* games(); 141 bool update_for_clients(); 142 const std::vector<InternetClient>* clients(); 143 144 /// sets the name of the local server as shown in the games list set_local_servernameInternetGaming145 void set_local_servername(const std::string& name) { 146 gamename_ = name; 147 } 148 149 /// \returns the name of the local server get_local_servernameInternetGaming150 std::string& get_local_servername() { 151 return gamename_; 152 } 153 154 /// \returns the name of the local client get_local_clientnameInternetGaming155 std::string& get_local_clientname() { 156 return clientname_; 157 } 158 159 /// \returns the rights of the local client get_local_clientrightsInternetGaming160 std::string& get_local_clientrights() { 161 return clientrights_; 162 } 163 164 /// ChatProvider: sends a message via the metaserver. 165 void send(const std::string&) override; 166 167 /// ChatProvider: adds the message to the message list and calls parent. receiveInternetGaming168 void receive(const ChatMessage& msg) { 169 messages_.push_back(msg); 170 Notifications::publish(msg); 171 } 172 173 /// ChatProvider: returns the list of chatmessages. get_messagesInternetGaming174 const std::vector<ChatMessage>& get_messages() const override { 175 return messages_; 176 } 177 178 /// Silence the internet lobby chat if we are in game as we do not see the messages anyways sound_offInternetGaming179 bool sound_off() override { 180 return state_ == IN_GAME; 181 } 182 183 /// writes the ingame_system_chat_ messages to \arg msg and resets it afterwards get_ingame_system_messagesInternetGaming184 void get_ingame_system_messages(std::vector<ChatMessage>& msg) { 185 msg = ingame_system_chat_; 186 ingame_system_chat_.clear(); 187 } 188 has_been_setInternetGaming189 bool has_been_set() const override { 190 return true; 191 } 192 193 void format_and_add_chat(const std::string& from, 194 const std::string& to, 195 bool system, 196 const std::string& msg); 197 198 bool valid_username(std::string); 199 200 private: 201 InternetGaming(); 202 203 /** 204 * Temporarily creates a second connection to the metaserver. 205 * If the primary connection is an IPv6 connection, we also try 206 * an IPv4 connection to tell the metaserver our IP. 207 * This way, when we host a game later on, the metaserver 208 * knows how to reach us for both protocol versions. 209 * The established connection does a login, then the connection is 210 * immediately closed. 211 * 212 * If the primary connection already is IPv4, this method does nothing. 213 * Since we first try to connect with IPv6, another try is futile. 214 */ 215 void create_second_connection(); 216 217 void handle_packet(RecvPacket& packet, bool relogin_on_error = true); 218 void handle_failed_read(); 219 220 // conversion functions 221 bool str2bool(std::string); 222 std::string bool2str(bool); 223 224 /** 225 * Does the real work of the login. 226 * \param relogin Whether this is a relogin. Only difference is that 227 * on first login a greeting is shown. 228 */ 229 bool do_login(bool relogin = false); 230 231 /// The connection to the metaserver 232 std::unique_ptr<NetClient> net; 233 234 /// Current state of this class 235 enum { OFFLINE, CONNECTING, LOBBY, IN_GAME, COMMUNICATION_ERROR } state_; 236 237 /// data saved for possible relogin 238 std::string authenticator_; 239 bool reg_; 240 241 /// Password for connecting as host to a game on the relay server 242 std::string relay_password_; 243 244 std::string meta_; 245 uint16_t port_; 246 247 /// local clients name and rights 248 std::string clientname_; 249 std::string clientrights_; 250 251 /// information of the clients game 252 std::string gamename_; 253 /// The IPv4/v6 addresses of the game host we are / will be connected to. 254 /// See InternetGaming::ips(). 255 std::pair<NetAddress, NetAddress> gameips_; 256 257 /// Metaserver information 258 bool clientupdateonmetaserver_; 259 bool gameupdateonmetaserver_; 260 bool clientupdate_; 261 bool gameupdate_; 262 std::vector<InternetClient> clientlist_; 263 std::vector<InternetGame> gamelist_; 264 int32_t time_offset_; 265 266 /// ChatProvider: chat messages 267 std::vector<ChatMessage> messages_; 268 std::vector<ChatMessage> ingame_system_chat_; 269 270 /// An important response of the metaserver, the client is waiting for. 271 std::string waitcmd_; 272 int32_t waittimeout_; 273 274 /// Connection tracking specific variables 275 time_t lastbrokensocket_[2]; /// last times when socket last broke in s. 276 time_t lastping_; 277 }; 278 279 #endif // end of include guard: WL_NETWORK_INTERNET_GAMING_H 280