Revamp CNShared logic

* Use a specialized connection object
* Copy the Player object less frequently
* Use a randomly generated serial key for shard auth
* Refuse invalid shard connection attempts
* Clean up connection metadata when a Player joins the shard
* Prune abandoned connections when they time out
This commit is contained in:
2022-07-24 00:16:04 +02:00
parent c5dd745aa1
commit 741bfb675b
6 changed files with 78 additions and 48 deletions

View File

@@ -5,23 +5,47 @@
#else
#include <mutex>
#endif
std::map<int64_t, Player> CNShared::players;
std::mutex playerCrit;
void CNShared::setPlayer(int64_t sk, Player& plr) {
std::lock_guard<std::mutex> lock(playerCrit); // the lock will be removed when the function ends
static std::unordered_map<int64_t, LoginMetadata*> login;
static std::mutex mtx;
players[sk] = plr;
void CNShared::storeLoginMetadata(int64_t sk, LoginMetadata *lm) {
std::lock_guard<std::mutex> lock(mtx);
// take ownership of connection data
login[sk] = lm;
}
Player CNShared::getPlayer(int64_t sk) {
std::lock_guard<std::mutex> lock(playerCrit); // the lock will be removed when the function ends
LoginMetadata* CNShared::getLoginMetadata(int64_t sk) {
std::lock_guard<std::mutex> lock(mtx);
return players[sk];
// fail if the key isn't found
if (login.find(sk) == login.end())
return nullptr;
// transfer ownership of connection data to shard
LoginMetadata *lm = login[sk];
login.erase(sk);
return lm;
}
void CNShared::erasePlayer(int64_t sk) {
std::lock_guard<std::mutex> lock(playerCrit); // the lock will be removed when the function ends
void CNShared::pruneLoginMetadata(CNServer *serv, time_t currTime) {
std::lock_guard<std::mutex> lock(mtx);
players.erase(sk);
auto it = login.begin();
while (it != login.end()) {
auto& sk = it->first;
auto& lm = it->second;
if (lm->timestamp + CNSHARED_TIMEOUT > currTime) {
std::cout << "[WARN] Pruning hung connection attempt" << std::endl;
// deallocate object and remove map entry
delete login[sk];
it = login.erase(it); // skip the invalidated iterator
} else {
it++;
}
}
}

View File

@@ -10,11 +10,16 @@
#include "Player.hpp"
namespace CNShared {
// serialkey corresponds to player data
extern std::map<int64_t, Player> players;
#define CNSHARED_TIMEOUT 30000
void setPlayer(int64_t sk, Player& plr);
Player getPlayer(int64_t sk);
void erasePlayer(int64_t sk);
struct LoginMetadata {
uint64_t FEKey;
Player plr;
time_t timestamp;
};
namespace CNShared {
void storeLoginMetadata(int64_t sk, LoginMetadata *lm);
LoginMetadata* getLoginMetadata(int64_t sk);
void pruneLoginMetadata(CNServer *serv, time_t currTime);
}