Simplify STUN and LAN connection
Using enet intercept directly
This commit is contained in:
parent
3cdc1b6ddd
commit
88e1733d50
@ -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/*")
|
||||
|
@ -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"))
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 <algorithm>
|
||||
// ============================================================================
|
||||
std::weak_ptr<bool> 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> 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<std::string> 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<std::string> 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<RequestConnection>(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
|
||||
|
||||
|
@ -31,39 +31,32 @@ class Server;
|
||||
class ConnectToServer : public Protocol
|
||||
{
|
||||
private:
|
||||
uint64_t m_timer = 0;
|
||||
TransportAddress m_server_address;
|
||||
std::shared_ptr<Server> m_server;
|
||||
unsigned m_tried_connection = 0;
|
||||
|
||||
/** Protocol currently being monitored. */
|
||||
std::weak_ptr<Protocol> 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<ConnectState> 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<bool> m_previous_unjoin;
|
||||
ConnectToServer(std::shared_ptr<Server> 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
|
||||
|
||||
|
@ -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> 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
|
||||
|
@ -1,40 +0,0 @@
|
||||
#ifndef HEADER_REQUEST_CONNECTION_HPP
|
||||
#define HEADER_REQUEST_CONNECTION_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/xml_request.hpp"
|
||||
|
||||
#include <memory>
|
||||
class Server;
|
||||
|
||||
class RequestConnection : public Protocol
|
||||
{
|
||||
protected:
|
||||
/** Id of the server to join. */
|
||||
std::shared_ptr<Server> m_server;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
EXITING
|
||||
};
|
||||
|
||||
/** State of this connection. */
|
||||
STATE m_state;
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
RequestConnection(std::shared_ptr<Server> 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
|
@ -1217,13 +1217,16 @@ std::shared_ptr<STKPeer> 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<STKPeer>(event.peer, this,
|
||||
m_next_unique_host_id++);
|
||||
stk_peer->setValidated();
|
||||
|
@ -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<std::shared_ptr<STKPeer> > 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<uint32_t, uint32_t> getPeerPings()
|
||||
{ return m_peer_pings.getAtomic(); }
|
||||
|
@ -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"
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user