From 88e1733d50cbd02f0c4b61ecfe264f1171986042 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 7 Sep 2018 01:40:32 +0800 Subject: [PATCH] Simplify STUN and LAN connection Using enet intercept directly --- sources.cmake | 2 +- src/main.cpp | 8 +- src/network/network_config.cpp | 1 - src/network/network_config.hpp | 4 - src/network/protocols/connect_to_peer.cpp | 10 +- src/network/protocols/connect_to_server.cpp | 453 ++++++++----------- src/network/protocols/connect_to_server.hpp | 19 +- src/network/protocols/request_connection.cpp | 124 ----- src/network/protocols/request_connection.hpp | 40 -- src/network/stk_host.cpp | 11 +- src/network/stk_host.hpp | 4 +- src/states_screens/online_lan.cpp | 10 - src/states_screens/online_screen.cpp | 2 +- 13 files changed, 206 insertions(+), 482 deletions(-) delete mode 100644 src/network/protocols/request_connection.cpp delete mode 100644 src/network/protocols/request_connection.hpp diff --git a/sources.cmake b/sources.cmake index d4f28ae4d..ba4868d71 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,5 +1,5 @@ # Modify this file to change the last-modified date when you add/remove a file. -# This will then trigger a new cmake run automatically. +# This will then trigger a new cmake run automatically. file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") diff --git a/src/main.cpp b/src/main.cpp index 4c44e16fc..5822c6210 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -608,7 +608,6 @@ void cmdLineHelp() " --init-user Save the above login and password (if set) in config.\n" " --disable-polling Don't poll for logged in user.\n" " --port=n Port number to use.\n" - " --disable-lan Disable LAN detection (connect using WAN).\n" " --auto-connect Automatically connect to fist server and start race\n" " --max-players=n Maximum number of clients (server only).\n" " --min-players=n Minimum number of clients (server only).\n" @@ -1204,7 +1203,7 @@ int handleCmdLine() cts->setup(); Log::info("main", "Trying to connect to server '%s'.", server_addr.toString().c_str()); - if (!cts->handleDirectConnect(10000)) + if (!cts->tryConnect(2000, 15)) { Log::error("main", "Timeout trying to connect to server '%s'.", server_addr.toString().c_str()); @@ -1356,11 +1355,6 @@ int handleCmdLine() if (server_lobby) server_lobby->requestStart(); - /** Disable detection of LAN connection when connecting via WAN. This is - * mostly a debugging feature to force using WAN connection. */ - if (CommandLine::has("--disable-lan")) - NetworkConfig::m_disable_lan = true; - // Race parameters if(CommandLine::has("--kartsize-debug")) { diff --git a/src/network/network_config.cpp b/src/network/network_config.cpp index 860e76602..ab9939c19 100644 --- a/src/network/network_config.cpp +++ b/src/network/network_config.cpp @@ -28,7 +28,6 @@ #include "states_screens/online_screen.hpp" NetworkConfig *NetworkConfig::m_network_config = NULL; -bool NetworkConfig::m_disable_lan = false; const uint32_t NetworkConfig::m_server_version = 1; /** \class NetworkConfig diff --git a/src/network/network_config.hpp b/src/network/network_config.hpp index ed0fdf709..b50847560 100644 --- a/src/network/network_config.hpp +++ b/src/network/network_config.hpp @@ -124,10 +124,6 @@ private: uint32_t m_joined_server_version; public: - /** Stores the command line flag to disable lan detection (i.e. force - * WAN code to be used when connection client and server). */ - static bool m_disable_lan; - /** Server version, will be advanced if there are protocol changes. */ static const uint32_t m_server_version; diff --git a/src/network/protocols/connect_to_peer.cpp b/src/network/protocols/connect_to_peer.cpp index d4dbe72c0..4ccb1a682 100644 --- a/src/network/protocols/connect_to_peer.cpp +++ b/src/network/protocols/connect_to_peer.cpp @@ -59,13 +59,15 @@ void ConnectToPeer::asynchronousUpdate() { m_timer = StkTime::getRealTimeMs(); // Send a broadcast packet with the string aloha_stk inside, - // the client will know our ip address and will connect - // The wan remote should already start its ping message to us now - // so we can send packet directly to it. + // the client will use enet intercept to discover if server + // address or port is different from stk addons database. + // (Happens if there is firewall in between) TransportAddress broadcast_address; broadcast_address = m_peer_address; - BareNetworkString aloha(std::string("aloha_stk")); + // Enet packet will not have 0xFFFF for first 2 bytes + BareNetworkString aloha("aloha-stk"); + aloha.getBuffer().insert(aloha.getBuffer().begin(), 2, 0xFF); STKHost::get()->sendRawPacket(aloha, broadcast_address); Log::verbose("ConnectToPeer", "Broadcast aloha sent."); StkTime::sleep(1); diff --git a/src/network/protocols/connect_to_server.cpp b/src/network/protocols/connect_to_server.cpp index f329a2a52..5131b6847 100644 --- a/src/network/protocols/connect_to_server.cpp +++ b/src/network/protocols/connect_to_server.cpp @@ -23,13 +23,13 @@ #include "network/event.hpp" #include "network/network.hpp" #include "network/network_config.hpp" -#include "network/protocols/request_connection.hpp" #include "network/protocols/client_lobby.hpp" #include "network/protocol_manager.hpp" #include "network/servers_manager.hpp" #include "network/server.hpp" #include "network/stk_host.hpp" #include "network/stk_peer.hpp" +#include "online/xml_request.hpp" #include "states_screens/networking_lobby.hpp" #include "utils/time.hpp" #include "utils/log.hpp" @@ -37,6 +37,9 @@ #include // ============================================================================ std::weak_ptr ConnectToServer::m_previous_unjoin; +TransportAddress ConnectToServer::m_server_address; +int ConnectToServer::m_retry_count = 0; +bool ConnectToServer::m_done_intecept = false; // ---------------------------------------------------------------------------- /** Specify server to connect to. * \param server Server to connect to (if nullptr than we use quick play). @@ -49,7 +52,6 @@ ConnectToServer::ConnectToServer(std::shared_ptr server) m_server = server; m_server_address = m_server->getAddress(); } - setHandleConnections(true); } // ConnectToServer(server, host) // ---------------------------------------------------------------------------- @@ -75,78 +77,77 @@ ConnectToServer::~ConnectToServer() void ConnectToServer::setup() { Log::info("ConnectToServer", "SETUP"); - m_current_protocol.reset(); // In case of LAN or client-server we already have the server's // and our ip address, so we can immediately start requesting a connection. m_state = NetworkConfig::get()->isLAN() ? GOT_SERVER_ADDRESS : SET_PUBLIC_ADDRESS; } // setup +// ---------------------------------------------------------------------------- +void ConnectToServer::getClientServerInfo() +{ + assert(m_server); + // Allow up to 10 seconds for the separate process to fully start-up + bool started = false; + uint64_t timeout = StkTime::getRealTimeMs() + 10000; + const std::string& sid = NetworkConfig::get()->getServerIdFile(); + assert(!sid.empty()); + const std::string dir = StringUtils::getPath(sid); + const std::string server_id_file = StringUtils::getBasename(sid); + uint16_t port = 0; + unsigned server_id = 0; + while (StkTime::getRealTimeMs() < timeout) + { + std::set files; + file_manager->listFiles(files, dir); + for (auto& f : files) + { + if (f.find(server_id_file) != std::string::npos) + { + auto split = StringUtils::split(f, '_'); + if (split.size() != 3) + continue; + if (!StringUtils::fromString(split[1], server_id)) + continue; + if (!StringUtils::fromString(split[2], port)) + continue; + file_manager->removeFile(dir + "/" + f); + started = true; + break; + } + } + if (started) + break; + StkTime::sleep(10); + } + NetworkConfig::get()->setServerIdFile(""); + if (!started) + { + Log::error("ConnectToServer", + "Separate server process failed to started"); + m_state = DONE; + return; + } + else + { + assert(port != 0); + m_server_address.setPort(port); + m_server->setPrivatePort(port); + if (server_id != 0) + { + m_server->setSupportsEncryption(true); + m_server->setServerId(server_id); + } + } +} // getClientServerInfo + // ---------------------------------------------------------------------------- void ConnectToServer::asynchronousUpdate() { if (STKHost::get()->isClientServer() && !NetworkConfig::get()->getServerIdFile().empty()) { - assert(m_server); - // Allow up to 10 seconds for the separate process to fully start-up - bool started = false; - uint64_t timeout = StkTime::getRealTimeMs() + 10000; - const std::string& sid = NetworkConfig::get()->getServerIdFile(); - assert(!sid.empty()); - const std::string dir = StringUtils::getPath(sid); - const std::string server_id_file = StringUtils::getBasename(sid); - uint16_t port = 0; - unsigned server_id = 0; - while (StkTime::getRealTimeMs() < timeout) - { - std::set files; - file_manager->listFiles(files, dir); - for (auto& f : files) - { - if (f.find(server_id_file) != std::string::npos) - { - auto split = StringUtils::split(f, '_'); - if (split.size() != 3) - continue; - if (!StringUtils::fromString(split[1], server_id)) - continue; - if (!StringUtils::fromString(split[2], port)) - continue; - file_manager->removeFile(dir + "/" + f); - started = true; - break; - } - } - if (started) - break; - StkTime::sleep(10); - } - NetworkConfig::get()->setServerIdFile(""); - if (!started) - { - Log::error("ConnectToServer", - "Separate server process failed to started"); - m_state = DONE; - return; - } - else - { - assert(port != 0); - m_server_address.setPort(port); - m_server->setPrivatePort(port); - if (server_id != 0) - { - m_server->setSupportsEncryption(true); - m_server->setServerId(server_id); - } - if (NetworkConfig::get()->isLAN() && - handleDirectConnect(5000)) - { - m_state = DONE; - return; - } - } + getClientServerInfo(); } switch(m_state.load()) @@ -204,110 +205,42 @@ void ConnectToServer::asynchronousUpdate() STKHost::get()->setPublicAddress(); registerWithSTKServer(); } - // Assume official server is firewall-less so give it more time - // to directly connect - if (handleDirectConnect((m_server->isOfficial() || - STKHost::get()->isClientServer()) ? 5000 : 2000)) - return; // Set to DONE will stop STKHost is not connected m_state = STKHost::get()->getPublicAddress().isUnset() ? DONE : GOT_SERVER_ADDRESS; + break; } - break; case GOT_SERVER_ADDRESS: { - assert(m_server); - Log::info("ConnectToServer", "Server's address known"); - m_state = REQUESTING_CONNECTION; - auto request_connection = - std::make_shared(m_server); - request_connection->requestStart(); - m_current_protocol = request_connection; - // Reset timer for next usage - m_timer = 0; - break; - } - case REQUESTING_CONNECTION: - { - if (!m_current_protocol.expired()) - { - return; - } - - // Server knows we want to connect - Log::info("ConnectToServer", "Connection request made"); - if (m_server_address.isUnset()) - { - // server data not correct, stop - m_state = DONE; - Log::error("ConnectToServer", "Server address is %s", - m_server_address.toString().c_str()); - return; - } - if (m_tried_connection++ > 7) - { - if (NetworkConfig::get()->isWAN()) - { - Log::warn("ConnectToServer", "Timeout waiting for" - " aloha, trying to connect anyway."); - m_state = CONNECTING; - // Reset timer for next usage - m_timer = 0; - m_tried_connection = 0; - } - else - m_state = DONE; - return; - } - if ((!NetworkConfig::m_disable_lan && + if (!STKHost::get()->isClientServer() && m_server_address.getIP() == - STKHost::get()->getPublicAddress().getIP()) || - (NetworkConfig::get()->isLAN() || - STKHost::get()->isClientServer())) + STKHost::get()->getPublicAddress().getIP()) { - // We're in the same lan (same public ip address). - // The state will change to CONNECTING - waitingAloha(false/*is_wan*/); - } - else - { - // Send a 1-byte datagram, the remote host can simply ignore - // this datagram, to keep the port open (2 second each) - if (StkTime::getRealTimeMs() > m_timer + 2000) + Log::info("ConnectToServer", "Server is in the same lan"); + std::string str_msg("connection-request"); + BareNetworkString message(str_msg + + StringUtils::toString(m_server->getPrivatePort())); + // If use lan connection for wan server, send to all broadcast + // addresses + for (auto& addr : + ServersManager::get()->getBroadcastAddresses()) { - m_timer = StkTime::getRealTimeMs(); - BareNetworkString data; - data.addUInt8(0); - STKHost::get()->sendRawPacket(data, m_server_address); - } - waitingAloha(true/*is_wan*/); - } - break; - } - case CONNECTING: // waiting the server to answer our connection - { - // Every 5 seconds - if (StkTime::getRealTimeMs() > m_timer + 5000) - { - m_timer = StkTime::getRealTimeMs(); - STKHost::get()->stopListening(); - STKHost::get()->connect(m_server_address); - STKHost::get()->startListening(); - Log::info("ConnectToServer", "Trying to connect to %s", - m_server_address.toString().c_str()); - if (m_tried_connection++ > 1) - { - Log::error("ConnectToServer", "Timeout connect to %s", - m_server_address.toString().c_str()); - m_state = DONE; + for (int i = 0; i < 5; i++) + { + STKHost::get()->sendRawPacket(message, addr); + StkTime::sleep(1); + } } } - break; - } - case CONNECTED: - { - Log::info("ConnectToServer", "Connected"); - m_state = DONE; + // 30 seconds connecting timeout total, use another port to try + // direct connection to server first, if failed than use the one + // that has stun mapped, the first 8 seconds allow the server to + // start the connect to peer protocol first before the port is + // remapped + if (tryConnect(2000, 4, true/*another_port*/)) + break; + if (!tryConnect(2000, 11)) + m_state = DONE; break; } case DONE: @@ -321,8 +254,7 @@ void ConnectToServer::update(int ticks) { switch(m_state.load()) { - case REQUESTING_CONNECTION: - case CONNECTING: + case GOT_SERVER_ADDRESS: { // Make sure lobby display the quick play server name assert(m_server); @@ -359,65 +291,103 @@ void ConnectToServer::update(int ticks) } // update // ---------------------------------------------------------------------------- -bool ConnectToServer::handleDirectConnect(int timeout) +/** Intercept callback in enet to allow change server address and port if + * needed (Happens when there is firewall in between) + */ +int ConnectToServer::interceptCallback(ENetHost* host, ENetEvent* event) { - // Direct connection to server should only possbile if public and private - // ports of server are the same - if ((NetworkConfig::get()->isWAN() && - m_server->getPrivatePort() == m_server->getAddress().getPort()) || - STKHost::get()->isClientServer()) + if (m_done_intecept) + return 0; + // The first two bytes of a valid ENet protocol packet will never be 0xFFFF + // and then try decode the string "aloha-stk" + if (host->receivedDataLength == 12 && + host->receivedData[0] == 0xFF && host->receivedData[1] == 0xFF && + host->receivedData[2] == 0x09 && host->receivedData[3] == 'a' && + host->receivedData[4] == 'l' && host->receivedData[5] == 'o' && + host->receivedData[6] == 'h' && host->receivedData[7] == 'a' && + host->receivedData[8] == '-' && host->receivedData[9] == 's' && + host->receivedData[10] == 't' && host->receivedData[11] == 'k') { - ENetEvent event; - ENetAddress ea; - ea.host = STKHost::HOST_ANY; - ea.port = STKHost::PORT_ANY; - Network* dc = new Network(/*peer_count*/1, - /*channel_limit*/EVENT_CHANNEL_COUNT, - /*max_in_bandwidth*/0, /*max_out_bandwidth*/0, &ea, - true/*change_port_if_bound*/); - assert(dc); - if (m_server_address.getPort() == 0) + TransportAddress server_addr = host->receivedAddress; + if (server_addr != m_server_address) { - // Get the server port of server from (common) server discovery port - Log::info("ConnectToServer", "Detect port for server address."); - BareNetworkString s(std::string("stk-server-port")); - TransportAddress address(m_server_address.getIP(), - NetworkConfig::get()->getServerDiscoveryPort()); - dc->sendRawPacket(s, address); - TransportAddress sender; - const int LEN = 2048; - char buffer[LEN]; - int len = dc->receiveRawPacket(buffer, LEN, &sender, 2000); - if (len != 2) - { - Log::error("ConnectToServer", "Invalid port number"); - delete dc; - return false; - } - BareNetworkString server_port(buffer, len); - uint16_t port = server_port.getUInt16(); - m_server_address.setPort(port); + Log::info("ConnectToServer", "Using new server address %s", + server_addr.toString().c_str()); + m_retry_count = 15; + m_server_address = server_addr; + m_done_intecept = true; + return 1; } - ENetPeer* p = dc->connectTo(m_server_address); - if (p) - { - while (enet_host_service(dc->getENetHost(), &event, timeout) != 0) - { - if (event.type == ENET_EVENT_TYPE_CONNECT) - { - Log::info("ConnectToServer", - "Direct connection to %s succeed", - m_server_address.toString().c_str()); - STKHost::get()->replaceNetwork(event, dc); - m_state = DONE; - return true; - } - } - } - delete dc; } + // 0 means let enet handle this packet + return 0; +} // interceptCallback + +// ---------------------------------------------------------------------------- +bool ConnectToServer::tryConnect(int timeout, int retry, bool another_port) +{ + m_retry_count = retry; + ENetEvent event; + ENetAddress ea; + ea.host = STKHost::HOST_ANY; + ea.port = STKHost::PORT_ANY; + Network* nw = another_port ? new Network(/*peer_count*/1, + /*channel_limit*/EVENT_CHANNEL_COUNT, + /*max_in_bandwidth*/0, /*max_out_bandwidth*/0, &ea, + true/*change_port_if_bound*/) : STKHost::get()->getNetwork(); + assert(nw); + + if (m_server_address.getPort() == 0) + { + // Get the server port of server from (common) server discovery port + Log::info("ConnectToServer", "Detect port for server address."); + BareNetworkString s(std::string("stk-server-port")); + TransportAddress address(m_server_address.getIP(), + NetworkConfig::get()->getServerDiscoveryPort()); + nw->sendRawPacket(s, address); + TransportAddress sender; + const int LEN = 2048; + char buffer[LEN]; + int len = nw->receiveRawPacket(buffer, LEN, &sender, 2000); + if (len != 2) + { + Log::error("ConnectToServer", "Invalid port number"); + return false; + } + BareNetworkString server_port(buffer, len); + uint16_t port = server_port.getUInt16(); + m_server_address.setPort(port); + } + + m_done_intecept = false; + nw->getENetHost()->intercept = ConnectToServer::interceptCallback; + while (--m_retry_count >= 0 && !ProtocolManager::lock()->isExiting()) + { + ENetPeer* p = nw->connectTo(m_server_address); + if (!p) + break; + Log::info("ConnectToServer", "Trying connecting to %s from port %d, " + "retry remain: %d", m_server_address.toString().c_str(), + nw->getENetHost()->address.port, m_retry_count); + while (enet_host_service(nw->getENetHost(), &event, timeout) != 0) + { + if (event.type == ENET_EVENT_TYPE_CONNECT) + { + Log::info("ConnectToServer", "Connected to %s", + m_server_address.toString().c_str()); + nw->getENetHost()->intercept = NULL; + STKHost::get()->initClientNetwork(event, nw); + m_state = DONE; + return true; + } + } + // Reset old peer in case server address differs due to intercept + enet_peer_reset(p); + } + if (another_port) + delete nw; return false; -} // handleDirectConnect +} // tryConnect // ---------------------------------------------------------------------------- /** Register this client with the STK server. @@ -452,7 +422,7 @@ void ConnectToServer::registerWithSTKServer() // network requests request->executeNow(); - const XMLNode * result = request->getXMLData(); + const XMLNode* result = request->getXMLData(); std::string success; if(result->get("success", &success) && success == "yes") @@ -469,64 +439,3 @@ void ConnectToServer::registerWithSTKServer() delete request; } // registerWithSTKServer - -// ---------------------------------------------------------------------------- -/** Called when the server is on the same LAN. It uses broadcast to - * find and conntect to the server. For WAN game, it makes sure server recieve - * request from stk addons first before continuing. - */ -void ConnectToServer::waitingAloha(bool is_wan) -{ - // just send a broadcast packet, the client will know our - // ip address and will connect - STKHost::get()->stopListening(); // stop the listening - Log::info("ConnectToServer", "Waiting broadcast message."); - - TransportAddress sender; - // get the sender - const int LEN=256; - char buffer[LEN]; - int len = STKHost::get()->receiveRawPacket(buffer, LEN, &sender, 2000); - if(len<0) - { - Log::warn("ConnectToServer", - "Received invalid server information message."); - return; - } - - BareNetworkString message(buffer, len); - std::string received; - message.decodeString(&received); - std::string aloha("aloha_stk"); - if (received==aloha) - { - Log::info("ConnectToServer", "Server found : %s", - sender.toString().c_str()); - if (!is_wan) - { - if (sender.isPublicAddressLocalhost()) - sender.setIP(0x7f000001); // 127.0.0.1 - } - m_server_address = sender; - m_state = CONNECTING; - // Reset timer for next usage - m_timer = 0; - m_tried_connection = 0; - } -} // waitingAloha - -// ---------------------------------------------------------------------------- - -bool ConnectToServer::notifyEventAsynchronous(Event* event) -{ - if (event->getType() == EVENT_TYPE_CONNECTED) - { - Log::info("ConnectToServer", "The Connect To Server protocol has " - "received an event notifying that he's connected to the peer."); - // We received a message and connected, no need to check for address - // as only 1 peer possible in client - m_state = CONNECTED; - } - return true; -} // notifyEventAsynchronous - diff --git a/src/network/protocols/connect_to_server.hpp b/src/network/protocols/connect_to_server.hpp index 0db325eac..f99eacce9 100644 --- a/src/network/protocols/connect_to_server.hpp +++ b/src/network/protocols/connect_to_server.hpp @@ -31,39 +31,32 @@ class Server; class ConnectToServer : public Protocol { private: - uint64_t m_timer = 0; - TransportAddress m_server_address; std::shared_ptr m_server; - unsigned m_tried_connection = 0; - - /** Protocol currently being monitored. */ - std::weak_ptr m_current_protocol; /** State for finite state machine. */ enum ConnectState : unsigned int { SET_PUBLIC_ADDRESS, GOT_SERVER_ADDRESS, - REQUESTING_CONNECTION, - CONNECTING, - CONNECTED, DONE, EXITING }; std::atomic m_state; + void getClientServerInfo(); void registerWithSTKServer(); - void waitingAloha(bool is_wan); + static TransportAddress m_server_address; + static int interceptCallback(ENetHost* host, ENetEvent* event); + static int m_retry_count; + static bool m_done_intecept; public: static std::weak_ptr m_previous_unjoin; ConnectToServer(std::shared_ptr server); virtual ~ConnectToServer(); - - virtual bool notifyEventAsynchronous(Event* event) OVERRIDE; virtual void setup() OVERRIDE; virtual void asynchronousUpdate() OVERRIDE; virtual void update(int ticks) OVERRIDE; - bool handleDirectConnect(int timeout); + bool tryConnect(int timeout, int retry, bool another_port = false); }; // class ConnectToServer diff --git a/src/network/protocols/request_connection.cpp b/src/network/protocols/request_connection.cpp deleted file mode 100644 index 12a56971d..000000000 --- a/src/network/protocols/request_connection.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2013-2015 SuperTuxKart-Team -// -// This program 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; either version 3 -// of the License, or (at your option) any later version. -// -// This program 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. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "network/protocols/request_connection.hpp" - -#include "config/user_config.hpp" -#include "network/network.hpp" -#include "network/network_config.hpp" -#include "network/protocol_manager.hpp" -#include "network/server.hpp" -#include "network/servers_manager.hpp" -#include "network/stk_host.hpp" -#include "online/xml_request.hpp" -#include "utils/string_utils.hpp" - -using namespace Online; - -/** Constructor. Stores the server id. - * \param server Server to be joined. - */ -RequestConnection::RequestConnection(std::shared_ptr server) - : Protocol(PROTOCOL_SILENT) -{ - m_server = server; -} // RequestConnection - -// ---------------------------------------------------------------------------- -RequestConnection::~RequestConnection() -{ -} // ~RequestConnection - -// ---------------------------------------------------------------------------- -/** Setup of this request, sets state to none. - */ -void RequestConnection::setup() -{ - m_state = NONE; -} // setup - -// ---------------------------------------------------------------------------- -/** This implements a finite state machine to monitor the server join - * request asynchronously. - */ -void RequestConnection::asynchronousUpdate() -{ - switch (m_state) - { - case NONE: - { - if ((!NetworkConfig::m_disable_lan && - m_server->getAddress().getIP() == - STKHost::get()->getPublicAddress().getIP()) || - (NetworkConfig::get()->isLAN() || - STKHost::get()->isClientServer())) - { - if (NetworkConfig::get()->isWAN()) - { - Log::info("RequestConnection", - "LAN connection to WAN server will be used."); - } - - std::string str_msg("connection-request"); - BareNetworkString message(str_msg + - StringUtils::toString(m_server->getPrivatePort())); - - if (!NetworkConfig::m_disable_lan && - m_server->getAddress().getIP() == - STKHost::get()->getPublicAddress().getIP() && - !STKHost::get()->isClientServer()) - { - // If use lan connection in wan server, send to all - // broadcast address - for (auto& addr : - ServersManager::get()->getBroadcastAddresses()) - { - for (int i = 0; i < 5; i++) - { - STKHost::get()->sendRawPacket(message, addr); - StkTime::sleep(1); - } - } - } - else - { - TransportAddress server_addr; - server_addr.setIP(m_server->getAddress().getIP()); - // Direct socket always listens on server discovery port - server_addr.setPort(NetworkConfig::get() - ->getServerDiscoveryPort()); - // Avoid possible packet loss, the connect to peer done by - // server will auto terminate if same peer from same port - // has connected already - for (int i = 0; i < 5; i++) - { - STKHost::get()->sendRawPacket(message, server_addr); - StkTime::sleep(1); - } - } - - } - m_state = EXITING; - requestTerminate(); - break; - } - case EXITING: - break; - } -} // asynchronousUpdate - diff --git a/src/network/protocols/request_connection.hpp b/src/network/protocols/request_connection.hpp deleted file mode 100644 index 73f3e1b7f..000000000 --- a/src/network/protocols/request_connection.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef HEADER_REQUEST_CONNECTION_HPP -#define HEADER_REQUEST_CONNECTION_HPP - -#include "network/protocol.hpp" -#include "online/xml_request.hpp" - -#include -class Server; - -class RequestConnection : public Protocol -{ -protected: - /** Id of the server to join. */ - std::shared_ptr m_server; - enum STATE - { - NONE, - EXITING - }; - - /** State of this connection. */ - STATE m_state; - -public: - // ------------------------------------------------------------------------ - RequestConnection(std::shared_ptr server); - virtual ~RequestConnection(); - virtual void setup() OVERRIDE; - virtual void asynchronousUpdate() OVERRIDE; - // ------------------------------------------------------------------------ - virtual bool notifyEvent(Event* event) OVERRIDE { return true; } - // ------------------------------------------------------------------------ - virtual bool notifyEventAsynchronous(Event* event) OVERRIDE { return true; } - // ------------------------------------------------------------------------ - virtual void update(int ticks) OVERRIDE {} - - -}; // RequestConnection - -#endif // REQUEST_CONNECTION_HPP diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index 7dceec1cc..018df8df2 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -1217,13 +1217,16 @@ std::shared_ptr STKHost::findPeerByHostId(uint32_t id) const } // findPeerByHostId //----------------------------------------------------------------------------- -void STKHost::replaceNetwork(ENetEvent& event, Network* network) +void STKHost::initClientNetwork(ENetEvent& event, Network* new_network) { assert(NetworkConfig::get()->isClient()); assert(!m_listening_thread.joinable()); - assert(network->getENetHost()->peerCount == 1); - delete m_network; - m_network = network; + assert(new_network->getENetHost()->peerCount == 1); + if (m_network != new_network) + { + delete m_network; + m_network = new_network; + } auto stk_peer = std::make_shared(event.peer, this, m_next_unique_host_id++); stk_peer->setValidated(); diff --git a/src/network/stk_host.hpp b/src/network/stk_host.hpp index 76a668adf..e2724331a 100644 --- a/src/network/stk_host.hpp +++ b/src/network/stk_host.hpp @@ -280,6 +280,8 @@ public: m_network->sendRawPacket(buffer, dst); } // sendRawPacket // ------------------------------------------------------------------------ + Network* getNetwork() const { return m_network; } + // ------------------------------------------------------------------------ /** Returns a copied list of peers. */ std::vector > getPeers() const { @@ -318,7 +320,7 @@ public: * creation screen. */ bool isClientServer() const { return m_separate_process != NULL; } // ------------------------------------------------------------------------ - void replaceNetwork(ENetEvent& event, Network* network); + void initClientNetwork(ENetEvent& event, Network* new_network); // ------------------------------------------------------------------------ std::map getPeerPings() { return m_peer_pings.getAtomic(); } diff --git a/src/states_screens/online_lan.cpp b/src/states_screens/online_lan.cpp index f9ee8be00..d32fd47c5 100644 --- a/src/states_screens/online_lan.cpp +++ b/src/states_screens/online_lan.cpp @@ -17,20 +17,10 @@ #include "states_screens/online_profile_servers.hpp" -#include "audio/sfx_manager.hpp" -#include "config/player_manager.hpp" -#include "guiengine/engine.hpp" -#include "guiengine/scalable_font.hpp" #include "guiengine/screen.hpp" -#include "guiengine/widget.hpp" #include "network/network_config.hpp" -#include "network/protocol_manager.hpp" -#include "network/protocols/connect_to_server.hpp" -#include "network/protocols/request_connection.hpp" -#include "network/servers_manager.hpp" #include "states_screens/state_manager.hpp" #include "states_screens/create_server_screen.hpp" -#include "states_screens/networking_lobby.hpp" #include "states_screens/online_lan.hpp" #include "states_screens/server_selection.hpp" #include "utils/translation.hpp" diff --git a/src/states_screens/online_screen.cpp b/src/states_screens/online_screen.cpp index 64cb36e99..eec31e7fc 100644 --- a/src/states_screens/online_screen.cpp +++ b/src/states_screens/online_screen.cpp @@ -267,7 +267,7 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name, cts->setup(); Log::info("OnlineScreen", "Trying to connect to server '%s'.", server_addr.toString().c_str()); - if (!cts->handleDirectConnect(10000)) + if (!cts->tryConnect(2000, 15)) { core::stringw err = _("Cannot connect to server %s.", server_addr.toString().c_str());