Use request manager to handle server recovery and registration

This commit is contained in:
Benau
2020-02-29 01:16:20 +08:00
parent e31bd30f1f
commit 8b119201dc
2 changed files with 75 additions and 74 deletions

View File

@@ -232,9 +232,9 @@ ServerLobby::ServerLobby() : LobbyProtocol()
m_rs_state.store(RS_NONE);
m_last_success_poll_time.store(StkTime::getMonoTimeMs() + 30000);
m_last_unsuccess_poll_time = StkTime::getMonoTimeMs();
m_server_owner_id.store(-1);
m_registered_for_once_only = false;
m_has_created_server_id_file = false;
setHandleDisconnections(true);
m_state = SET_PUBLIC_ADDRESS;
m_save_server_config = true;
@@ -260,8 +260,7 @@ ServerLobby::ServerLobby() : LobbyProtocol()
*/
ServerLobby::~ServerLobby()
{
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isWAN())
if (m_server_id_online.load() != 0)
{
// For child process the request manager will keep on running
unregisterServer(m_process_type == PT_MAIN ? true : false/*now*/);
@@ -864,27 +863,6 @@ bool ServerLobby::notifyEventAsynchronous(Event* event)
return true;
} // notifyEventAsynchronous
//-----------------------------------------------------------------------------
/** Create the server id file to let the graphics server client connect. */
void ServerLobby::createServerIdFile()
{
std::string sid = NetworkConfig::get()->getServerIdFile();
if (!sid.empty() && !m_has_created_server_id_file)
{
std::fstream fs;
sid += StringUtils::toString(m_server_id_online.load()) + "_" +
StringUtils::toString(STKHost::get()->getPrivatePort());
if (isIPv6Socket())
sid += "_v6";
else
sid += "_v4";
io::IWriteFile* file = irr::io::createWriteFile(sid.c_str(), false);
if (file)
file->drop();
m_has_created_server_id_file = true;
}
} // createServerIdFile
//-----------------------------------------------------------------------------
#ifdef ENABLE_SQLITE3
/* Every 1 minute STK will poll database:
@@ -1346,18 +1324,22 @@ void ServerLobby::asynchronousUpdate()
if (allowJoinedPlayersWaiting() || (m_game_setup->isGrandPrix() &&
m_state.load() == WAITING_FOR_START_GAME))
{
// Only poll the STK server if this is a WAN server.
if (NetworkConfig::get()->isWAN())
// Only poll the STK server if server has been registered.
if (m_server_id_online.load() != 0 &&
m_state.load() != REGISTER_SELF_ADDRESS)
checkIncomingConnectionRequests();
handlePendingConnection();
}
if (NetworkConfig::get()->isWAN() &&
allowJoinedPlayersWaiting() && m_server_recovering.expired() &&
if (m_server_id_online.load() != 0 &&
allowJoinedPlayersWaiting() &&
StkTime::getMonoTimeMs() > m_last_unsuccess_poll_time &&
StkTime::getMonoTimeMs() > m_last_success_poll_time.load() + 30000)
{
Log::warn("ServerLobby", "Trying auto server recovery.");
registerServer(false/*now*/);
// For auto server recovery wait 3 seconds for next try
m_last_unsuccess_poll_time = StkTime::getMonoTimeMs() + 3000;
registerServer();
}
switch (m_state.load())
@@ -1370,7 +1352,6 @@ void ServerLobby::asynchronousUpdate()
{
m_state = WAITING_FOR_START_GAME;
STKHost::get()->startListening();
createServerIdFile();
return;
}
auto ip_type = NetworkConfig::get()->getIPType();
@@ -1406,16 +1387,25 @@ void ServerLobby::asynchronousUpdate()
// Register this server with the STK server. This will block
// this thread, because there is no need for the protocol manager
// to react to any requests before the server is registered.
if (registerServer(true/*now*/))
if (m_server_registering.expired() && m_server_id_online.load() == 0)
registerServer();
if (m_server_registering.expired())
{
if (allowJoinedPlayersWaiting())
m_registered_for_once_only = true;
m_state = WAITING_FOR_START_GAME;
createServerIdFile();
}
else
{
m_state = ERROR_LEAVE;
// Finished registering server
if (m_server_id_online.load() != 0)
{
// For non grand prix server we only need to register to stk
// addons once
if (allowJoinedPlayersWaiting())
m_registered_for_once_only = true;
m_state = WAITING_FOR_START_GAME;
}
else
{
// Exit now if failed to register to stk addons
m_state = ERROR_LEAVE;
}
}
break;
}
@@ -2189,14 +2179,13 @@ void ServerLobby::update(int ticks)
* ProtocolManager thread). The information about this client is added
* to the table 'server'.
*/
bool ServerLobby::registerServer(bool now)
void ServerLobby::registerServer()
{
// ========================================================================
class RegisterServerRequest : public Online::XMLRequest
{
private:
std::weak_ptr<ServerLobby> m_server_lobby;
const bool m_execute_now;
protected:
virtual void afterOperation()
{
@@ -2232,18 +2221,14 @@ bool ServerLobby::registerServer(bool now)
}
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 (!m_execute_now)
StkTime::sleep(3000);
}
public:
RegisterServerRequest(bool now, std::shared_ptr<ServerLobby> sl)
RegisterServerRequest(std::shared_ptr<ServerLobby> sl)
: XMLRequest(Online::RequestManager::HTTP_MAX_PRIORITY),
m_server_lobby(sl), m_execute_now(now) {}
m_server_lobby(sl) {}
}; // RegisterServerRequest
auto request = std::make_shared<RegisterServerRequest>(now,
auto request = std::make_shared<RegisterServerRequest>(
std::dynamic_pointer_cast<ServerLobby>(shared_from_this()));
NetworkConfig::get()->setServerDetails(request, "create");
const SocketAddress& addr = STKHost::get()->getPublicAddress();
@@ -2274,18 +2259,8 @@ bool ServerLobby::registerServer(bool now)
Log::info("ServerLobby", "Public IPv6 server address %s",
STKHost::get()->getPublicIPv6Address().c_str());
}
if (now)
{
request->executeNow();
if (m_server_id_online.load() == 0)
return false;
}
else
{
request->queue();
m_server_recovering = request;
}
return true;
request->queue();
m_server_registering = request;
} // registerServer
//-----------------------------------------------------------------------------
@@ -2293,10 +2268,38 @@ bool ServerLobby::registerServer(bool now)
* currently when karts enter kart selection screen it will be done or quit
* stk.
*/
void ServerLobby::unregisterServer(bool now)
void ServerLobby::unregisterServer(bool now, std::weak_ptr<ServerLobby> sl)
{
int priority = Online::RequestManager::HTTP_MAX_PRIORITY;
auto request = std::make_shared<Online::XMLRequest>(priority);
// ========================================================================
class UnRegisterServerRequest : 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;
if (result->get("success", &rec_success) &&
rec_success == "yes")
{
// Clear the server online for next register
// For grand prix server
if (auto sl = m_server_lobby.lock())
sl->m_server_id_online.store(0);
return;
}
Log::error("ServerLobby", "%s",
StringUtils::wideToUtf8(getInfo()).c_str());
}
public:
UnRegisterServerRequest(std::weak_ptr<ServerLobby> sl)
: XMLRequest(Online::RequestManager::HTTP_MAX_PRIORITY),
m_server_lobby(sl) {}
}; // UnRegisterServerRequest
auto request = std::make_shared<UnRegisterServerRequest>(sl);
NetworkConfig::get()->setServerDetails(request, "stop");
const SocketAddress& addr = STKHost::get()->getPublicAddress();
@@ -2508,9 +2511,10 @@ void ServerLobby::startSelection(const Event *event)
if (!allowJoinedPlayersWaiting())
{
ProtocolManager::lock()->findAndTerminate(PROTOCOL_CONNECTION);
if (NetworkConfig::get()->isWAN())
if (m_server_id_online.load() != 0)
{
unregisterServer(false/*now*/);
unregisterServer(false/*now*/,
std::dynamic_pointer_cast<ServerLobby>(shared_from_this()));
}
}
@@ -2569,8 +2573,7 @@ void ServerLobby::checkIncomingConnectionRequests()
const uint64_t POLL_INTERVAL = 5000;
static uint64_t last_poll_time = 0;
if (StkTime::getMonoTimeMs() < last_poll_time + POLL_INTERVAL ||
StkTime::getMonoTimeMs() > m_last_success_poll_time.load() + 30000 ||
m_server_id_online.load() == 0)
StkTime::getMonoTimeMs() > m_last_success_poll_time.load() + 30000)
return;
// Keep the port open, it can be sent to anywhere as we will send to the

View File

@@ -157,8 +157,6 @@ private:
/** Keeps track of the server state. */
std::atomic_bool m_server_has_loaded_world;
bool m_has_created_server_id_file;
bool m_registered_for_once_only;
bool m_save_server_config;
@@ -167,7 +165,7 @@ private:
std::map<std::weak_ptr<STKPeer>, bool,
std::owner_less<std::weak_ptr<STKPeer> > > m_peers_ready;
std::weak_ptr<Online::Request> m_server_recovering;
std::weak_ptr<Online::Request> m_server_registering;
/** Timeout counter for various state. */
std::atomic<int64_t> m_timeout;
@@ -219,7 +217,7 @@ private:
std::atomic<uint64_t> m_last_success_poll_time;
uint64_t m_server_started_at, m_server_delay;
uint64_t m_last_unsuccess_poll_time, m_server_started_at, m_server_delay;
// Default game settings if no one has ever vote, and save inside here for
// final vote (for live join)
@@ -246,14 +244,14 @@ private:
// Track(s) votes
void handlePlayerVote(Event *event);
void playerFinishedResult(Event *event);
bool registerServer(bool now);
void registerServer();
void finishedLoadingWorldClient(Event *event);
void finishedLoadingLiveJoinClient(Event *event);
void kickHost(Event* event);
void changeTeam(Event* event);
void handleChat(Event* event);
void unregisterServer(bool now);
void createServerIdFile();
void unregisterServer(bool now,
std::weak_ptr<ServerLobby> sl = std::weak_ptr<ServerLobby>());
void updatePlayerList(bool update_when_reset_server = false);
void updateServerOwner();
void handleServerConfiguration(Event* event);