Implement auto server recovery if connection to stk-addons is lost
This commit is contained in:
parent
f975e37dea
commit
6232140689
@ -93,6 +93,7 @@
|
|||||||
*/
|
*/
|
||||||
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
||||||
{
|
{
|
||||||
|
m_last_success_poll_time.store(StkTime::getRealTimeMs() + 30000);
|
||||||
m_waiting_players_counts.store(0);
|
m_waiting_players_counts.store(0);
|
||||||
m_server_owner_id.store(-1);
|
m_server_owner_id.store(-1);
|
||||||
m_registered_for_once_only = false;
|
m_registered_for_once_only = false;
|
||||||
@ -110,7 +111,7 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
|
|||||||
m_result_ns = getNetworkString();
|
m_result_ns = getNetworkString();
|
||||||
m_result_ns->setSynchronous(true);
|
m_result_ns->setSynchronous(true);
|
||||||
m_waiting_for_reset = false;
|
m_waiting_for_reset = false;
|
||||||
m_server_id_online = 0;
|
m_server_id_online.store(0);
|
||||||
} // ServerLobby
|
} // ServerLobby
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -356,7 +357,7 @@ void ServerLobby::createServerIdFile()
|
|||||||
if (!sid.empty() && !m_has_created_server_id_file)
|
if (!sid.empty() && !m_has_created_server_id_file)
|
||||||
{
|
{
|
||||||
std::fstream fs;
|
std::fstream fs;
|
||||||
sid += StringUtils::toString(m_server_id_online) + "_" +
|
sid += StringUtils::toString(m_server_id_online.load()) + "_" +
|
||||||
StringUtils::toString(STKHost::get()->getPrivatePort());
|
StringUtils::toString(STKHost::get()->getPrivatePort());
|
||||||
fs.open(sid, std::ios::out);
|
fs.open(sid, std::ios::out);
|
||||||
fs.close();
|
fs.close();
|
||||||
@ -384,6 +385,13 @@ void ServerLobby::asynchronousUpdate()
|
|||||||
handlePendingConnection();
|
handlePendingConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allowJoinedPlayersWaiting() && m_server_recovering.expired() &&
|
||||||
|
StkTime::getRealTimeMs() > m_last_success_poll_time.load() + 30000)
|
||||||
|
{
|
||||||
|
Log::warn("ServerLobby", "Trying auto server recovery.");
|
||||||
|
registerServer(false/*now*/);
|
||||||
|
}
|
||||||
|
|
||||||
switch (m_state.load())
|
switch (m_state.load())
|
||||||
{
|
{
|
||||||
case SET_PUBLIC_ADDRESS:
|
case SET_PUBLIC_ADDRESS:
|
||||||
@ -420,7 +428,7 @@ void ServerLobby::asynchronousUpdate()
|
|||||||
// Register this server with the STK server. This will block
|
// Register this server with the STK server. This will block
|
||||||
// this thread, because there is no need for the protocol manager
|
// this thread, because there is no need for the protocol manager
|
||||||
// to react to any requests before the server is registered.
|
// to react to any requests before the server is registered.
|
||||||
if (registerServer())
|
if (registerServer(true/*now*/))
|
||||||
{
|
{
|
||||||
if (allowJoinedPlayersWaiting())
|
if (allowJoinedPlayersWaiting())
|
||||||
m_registered_for_once_only = true;
|
m_registered_for_once_only = true;
|
||||||
@ -690,12 +698,56 @@ void ServerLobby::update(int ticks)
|
|||||||
* ProtocolManager thread). The information about this client is added
|
* ProtocolManager thread). The information about this client is added
|
||||||
* to the table 'server'.
|
* to the table 'server'.
|
||||||
*/
|
*/
|
||||||
bool ServerLobby::registerServer()
|
bool ServerLobby::registerServer(bool now)
|
||||||
{
|
{
|
||||||
while (!m_server_unregistered.expired())
|
while (now && !m_server_unregistered.expired())
|
||||||
StkTime::sleep(1);
|
StkTime::sleep(1);
|
||||||
|
|
||||||
Online::XMLRequest *request = new Online::XMLRequest();
|
// ========================================================================
|
||||||
|
class RegisterServerRequest : public Online::XMLRequest
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::weak_ptr<ServerLobby> m_server_lobby;
|
||||||
|
protected:
|
||||||
|
virtual void afterOperation()
|
||||||
|
{
|
||||||
|
Online::XMLRequest::afterOperation();
|
||||||
|
const XMLNode* result = getXMLData();
|
||||||
|
std::string rec_success;
|
||||||
|
auto sl = m_server_lobby.lock();
|
||||||
|
if (!sl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (result->get("success", &rec_success) &&
|
||||||
|
rec_success == "yes")
|
||||||
|
{
|
||||||
|
const XMLNode* server = result->getNode("server");
|
||||||
|
assert(server);
|
||||||
|
const XMLNode* server_info = server->getNode("server-info");
|
||||||
|
assert(server_info);
|
||||||
|
unsigned server_id_online = 0;
|
||||||
|
server_info->get("id", &server_id_online);
|
||||||
|
assert(server_id_online != 0);
|
||||||
|
Log::info("ServerLobby",
|
||||||
|
"Server %d is now online.", server_id_online);
|
||||||
|
sl->m_server_id_online.store(server_id_online);
|
||||||
|
sl->m_last_success_poll_time.store(StkTime::getRealTimeMs());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log::error("ServerLobby", "%s",
|
||||||
|
StringUtils::wideToUtf8(getInfo()).c_str());
|
||||||
|
// For auto server recovery wait 3 seconds for next try
|
||||||
|
// This sleep only the request manager thread
|
||||||
|
if (manageMemory())
|
||||||
|
StkTime::sleep(3000);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
RegisterServerRequest(bool now, std::shared_ptr<ServerLobby> sl)
|
||||||
|
: XMLRequest(!now/*manage memory*/), m_server_lobby(sl) {}
|
||||||
|
}; // RegisterServerRequest
|
||||||
|
|
||||||
|
RegisterServerRequest *request = new RegisterServerRequest(now,
|
||||||
|
std::dynamic_pointer_cast<ServerLobby>(shared_from_this()));
|
||||||
NetworkConfig::get()->setServerDetails(request, "create");
|
NetworkConfig::get()->setServerDetails(request, "create");
|
||||||
request->addParameter("address", m_server_address.getIP() );
|
request->addParameter("address", m_server_address.getIP() );
|
||||||
request->addParameter("port", m_server_address.getPort() );
|
request->addParameter("port", m_server_address.getPort() );
|
||||||
@ -715,29 +767,19 @@ bool ServerLobby::registerServer()
|
|||||||
Log::info("ServerLobby", "Public server address %s",
|
Log::info("ServerLobby", "Public server address %s",
|
||||||
m_server_address.toString().c_str());
|
m_server_address.toString().c_str());
|
||||||
|
|
||||||
request->executeNow();
|
if (now)
|
||||||
|
|
||||||
const XMLNode* result = request->getXMLData();
|
|
||||||
std::string rec_success;
|
|
||||||
|
|
||||||
if (result->get("success", &rec_success) && rec_success == "yes")
|
|
||||||
{
|
{
|
||||||
const XMLNode* server = result->getNode("server");
|
request->executeNow();
|
||||||
assert(server);
|
|
||||||
const XMLNode* server_info = server->getNode("server-info");
|
|
||||||
assert(server_info);
|
|
||||||
server_info->get("id", &m_server_id_online);
|
|
||||||
assert(m_server_id_online != 0);
|
|
||||||
Log::info("ServerLobby",
|
|
||||||
"Server %d is now online.", m_server_id_online);
|
|
||||||
delete request;
|
delete request;
|
||||||
return true;
|
if (m_server_id_online.load() == 0)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
irr::core::stringc error(request->getInfo().c_str());
|
{
|
||||||
Log::error("ServerLobby", "%s", error.c_str());
|
request->queue();
|
||||||
delete request;
|
m_server_recovering = request->observeExistence();
|
||||||
return false;
|
}
|
||||||
|
return true;
|
||||||
} // registerServer
|
} // registerServer
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -811,7 +853,7 @@ void ServerLobby::startSelection(const Event *event)
|
|||||||
if (!allowJoinedPlayersWaiting())
|
if (!allowJoinedPlayersWaiting())
|
||||||
{
|
{
|
||||||
ProtocolManager::lock()->findAndTerminate(PROTOCOL_CONNECTION);
|
ProtocolManager::lock()->findAndTerminate(PROTOCOL_CONNECTION);
|
||||||
if (NetworkConfig::get()->isWAN() )
|
if (NetworkConfig::get()->isWAN())
|
||||||
{
|
{
|
||||||
unregisterServer(false/*now*/);
|
unregisterServer(false/*now*/);
|
||||||
}
|
}
|
||||||
@ -903,7 +945,9 @@ void ServerLobby::checkIncomingConnectionRequests()
|
|||||||
// First poll every 5 seconds. Return if no polling needs to be done.
|
// First poll every 5 seconds. Return if no polling needs to be done.
|
||||||
const uint64_t POLL_INTERVAL = 5000;
|
const uint64_t POLL_INTERVAL = 5000;
|
||||||
static uint64_t last_poll_time = 0;
|
static uint64_t last_poll_time = 0;
|
||||||
if (StkTime::getRealTimeMs() < last_poll_time + POLL_INTERVAL)
|
if (StkTime::getRealTimeMs() < last_poll_time + POLL_INTERVAL ||
|
||||||
|
StkTime::getRealTimeMs() > m_last_success_poll_time.load() + 30000 ||
|
||||||
|
m_server_id_online.load() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Keep the port open, it can be sent to anywhere as we will send to the
|
// Keep the port open, it can be sent to anywhere as we will send to the
|
||||||
@ -927,12 +971,13 @@ void ServerLobby::checkIncomingConnectionRequests()
|
|||||||
virtual void afterOperation()
|
virtual void afterOperation()
|
||||||
{
|
{
|
||||||
Online::XMLRequest::afterOperation();
|
Online::XMLRequest::afterOperation();
|
||||||
const XMLNode *result = getXMLData();
|
const XMLNode* result = getXMLData();
|
||||||
std::string success;
|
std::string success;
|
||||||
|
|
||||||
if (!result->get("success", &success) || success != "yes")
|
if (!result->get("success", &success) || success != "yes")
|
||||||
{
|
{
|
||||||
Log::error("ServerLobby", "Cannot retrieve the list.");
|
Log::error("ServerLobby", "Poll server request failed: %s",
|
||||||
|
StringUtils::wideToUtf8(getInfo()).c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,6 +987,7 @@ void ServerLobby::checkIncomingConnectionRequests()
|
|||||||
auto sl = m_server_lobby.lock();
|
auto sl = m_server_lobby.lock();
|
||||||
if (!sl)
|
if (!sl)
|
||||||
return;
|
return;
|
||||||
|
sl->m_last_success_poll_time.store(StkTime::getRealTimeMs());
|
||||||
if (sl->m_state.load() != WAITING_FOR_START_GAME &&
|
if (sl->m_state.load() != WAITING_FOR_START_GAME &&
|
||||||
!sl->allowJoinedPlayersWaiting())
|
!sl->allowJoinedPlayersWaiting())
|
||||||
{
|
{
|
||||||
|
@ -95,6 +95,8 @@ private:
|
|||||||
/** It indicates if this server is unregistered with the stk server. */
|
/** It indicates if this server is unregistered with the stk server. */
|
||||||
std::weak_ptr<bool> m_server_unregistered;
|
std::weak_ptr<bool> m_server_unregistered;
|
||||||
|
|
||||||
|
std::weak_ptr<bool> m_server_recovering;
|
||||||
|
|
||||||
/** Timeout counter for various state. */
|
/** Timeout counter for various state. */
|
||||||
std::atomic<int64_t> m_timeout;
|
std::atomic<int64_t> m_timeout;
|
||||||
|
|
||||||
@ -148,9 +150,11 @@ private:
|
|||||||
|
|
||||||
std::atomic<uint32_t> m_waiting_players_counts;
|
std::atomic<uint32_t> m_waiting_players_counts;
|
||||||
|
|
||||||
|
std::atomic<uint64_t> m_last_success_poll_time;
|
||||||
|
|
||||||
uint64_t m_server_started_at, m_server_delay;
|
uint64_t m_server_started_at, m_server_delay;
|
||||||
|
|
||||||
unsigned m_server_id_online;
|
std::atomic<uint32_t> m_server_id_online;
|
||||||
|
|
||||||
bool m_registered_for_once_only;
|
bool m_registered_for_once_only;
|
||||||
|
|
||||||
@ -164,7 +168,7 @@ private:
|
|||||||
// Track(s) votes
|
// Track(s) votes
|
||||||
void playerVote(Event *event);
|
void playerVote(Event *event);
|
||||||
void playerFinishedResult(Event *event);
|
void playerFinishedResult(Event *event);
|
||||||
bool registerServer();
|
bool registerServer(bool now);
|
||||||
void finishedLoadingWorldClient(Event *event);
|
void finishedLoadingWorldClient(Event *event);
|
||||||
void kickHost(Event* event);
|
void kickHost(Event* event);
|
||||||
void changeTeam(Event* event);
|
void changeTeam(Event* event);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user