Skip to content

Commit

Permalink
Refactor OutputMessagePool: Extracted into tfs::net namespace (#4838)
Browse files Browse the repository at this point in the history
  • Loading branch information
ramon-bernardo authored Nov 18, 2024
1 parent 8b9e0b0 commit 14ba662
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 47 deletions.
25 changes: 14 additions & 11 deletions src/outputmessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ namespace {
const uint16_t OUTPUTMESSAGE_FREE_LIST_CAPACITY = 2048;
const std::chrono::milliseconds OUTPUTMESSAGE_AUTOSEND_DELAY{10};

// NOTE: A vector is used here because this container is mostly read and relatively rarely modified (only when a
// client connects/disconnects)
std::vector<Protocol_ptr> bufferedProtocols;

void sendAll(const std::vector<Protocol_ptr>& bufferedProtocols);

void scheduleSendAll(const std::vector<Protocol_ptr>& bufferedProtocols)
Expand All @@ -28,8 +32,7 @@ void sendAll(const std::vector<Protocol_ptr>& bufferedProtocols)
{
// dispatcher thread
for (auto& protocol : bufferedProtocols) {
auto& msg = protocol->getCurrentBuffer();
if (msg) {
if (auto& msg = protocol->getCurrentBuffer()) {
protocol->send(std::move(msg));
}
}
Expand All @@ -41,7 +44,14 @@ void sendAll(const std::vector<Protocol_ptr>& bufferedProtocols)

} // namespace

void OutputMessagePool::addProtocolToAutosend(Protocol_ptr protocol)
OutputMessage_ptr tfs::net::make_output_message()
{
// LockfreePoolingAllocator<void,...> will leave (void* allocate) ill-formed because of sizeof(T), so this
// guarantees that only one list will be initialized
return std::allocate_shared<OutputMessage>(LockfreePoolingAllocator<void, OUTPUTMESSAGE_FREE_LIST_CAPACITY>());
}

void tfs::net::insert_protocol_to_autosend(const Protocol_ptr& protocol)
{
// dispatcher thread
if (bufferedProtocols.empty()) {
Expand All @@ -50,7 +60,7 @@ void OutputMessagePool::addProtocolToAutosend(Protocol_ptr protocol)
bufferedProtocols.emplace_back(protocol);
}

void OutputMessagePool::removeProtocolFromAutosend(const Protocol_ptr& protocol)
void tfs::net::remove_protocol_from_autosend(const Protocol_ptr& protocol)
{
// dispatcher thread
auto it = std::find(bufferedProtocols.begin(), bufferedProtocols.end(), protocol);
Expand All @@ -59,10 +69,3 @@ void OutputMessagePool::removeProtocolFromAutosend(const Protocol_ptr& protocol)
bufferedProtocols.pop_back();
}
}

OutputMessage_ptr OutputMessagePool::getOutputMessage()
{
// LockfreePoolingAllocator<void,...> will leave (void* allocate) ill-formed because of sizeof(T), so this
// guarantees that only one list will be initialized
return std::allocate_shared<OutputMessage>(LockfreePoolingAllocator<void, OUTPUTMESSAGE_FREE_LIST_CAPACITY>());
}
27 changes: 5 additions & 22 deletions src/outputmessage.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,29 +62,12 @@ class OutputMessage : public NetworkMessage
MsgSize_t outputBufferStart = INITIAL_BUFFER_POSITION;
};

class OutputMessagePool
{
public:
// non-copyable
OutputMessagePool(const OutputMessagePool&) = delete;
OutputMessagePool& operator=(const OutputMessagePool&) = delete;
namespace tfs::net {

static OutputMessagePool& getInstance()
{
static OutputMessagePool instance;
return instance;
}
OutputMessage_ptr make_output_message();
void insert_protocol_to_autosend(const Protocol_ptr& protocol);
void remove_protocol_from_autosend(const Protocol_ptr& protocol);

static OutputMessage_ptr getOutputMessage();

void addProtocolToAutosend(Protocol_ptr protocol);
void removeProtocolFromAutosend(const Protocol_ptr& protocol);

private:
OutputMessagePool() = default;
// NOTE: A vector is used here because this container is mostly read and relatively rarely modified (only when a
// client connects/disconnects)
std::vector<Protocol_ptr> bufferedProtocols;
};
} // namespace tfs::net

#endif // FS_OUTPUTMESSAGE_H
4 changes: 2 additions & 2 deletions src/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ OutputMessage_ptr Protocol::getOutputBuffer(int32_t size)
{
// dispatcher thread
if (!outputBuffer) {
outputBuffer = OutputMessagePool::getOutputMessage();
outputBuffer = tfs::net::make_output_message();
} else if ((outputBuffer->getLength() + size) > NetworkMessage::MAX_PROTOCOL_BODY_LENGTH) {
send(outputBuffer);
outputBuffer = OutputMessagePool::getOutputMessage();
outputBuffer = tfs::net::make_output_message();
}
return outputBuffer;
}
Expand Down
16 changes: 10 additions & 6 deletions src/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ void ProtocolGame::release()
player = nullptr;
}

OutputMessagePool::getInstance().removeProtocolFromAutosend(shared_from_this());
tfs::net::remove_protocol_from_autosend(shared_from_this());

Protocol::release();
}

Expand Down Expand Up @@ -204,12 +205,13 @@ void ProtocolGame::login(uint32_t characterId, uint32_t accountId, OperatingSyst

if (std::size_t currentSlot = clientLogin(*player)) {
uint8_t retryTime = getWaitTime(currentSlot);
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();
output->addByte(0x16);
output->addString(
fmt::format("Too many players online.\nYou are at place {:d} on the waiting list.", currentSlot));
output->addByte(retryTime);
send(output);

disconnect();
return;
}
Expand Down Expand Up @@ -254,7 +256,8 @@ void ProtocolGame::login(uint32_t characterId, uint32_t accountId, OperatingSyst
connect(foundPlayer->getID(), operatingSystem);
}
}
OutputMessagePool::getInstance().addProtocolToAutosend(shared_from_this());

tfs::net::insert_protocol_to_autosend(shared_from_this());
}

void ProtocolGame::connect(uint32_t playerId, OperatingSystem_t operatingSystem)
Expand Down Expand Up @@ -455,7 +458,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)

void ProtocolGame::onConnect()
{
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();
static std::random_device rd;
static std::ranlux24 generator(rd());
static std::uniform_int_distribution<uint16_t> randNumber(0x00, 0xFF);
Expand Down Expand Up @@ -483,10 +486,11 @@ void ProtocolGame::onConnect()

void ProtocolGame::disconnectClient(const std::string& message) const
{
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();
output->addByte(0x14);
output->addString(message);
send(output);

disconnect();
}

Expand Down Expand Up @@ -3413,7 +3417,7 @@ void ProtocolGame::sendModalWindow(const ModalWindow& modalWindow)

void ProtocolGame::sendSessionEnd(SessionEndTypes_t reason)
{
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();
output->addByte(0x18);
output->addByte(reason);
send(output);
Expand Down
5 changes: 2 additions & 3 deletions src/protocollogin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ std::string decodeSecret(std::string_view secret)

void ProtocolLogin::disconnectClient(const std::string& message, uint16_t version)
{
auto output = OutputMessagePool::getOutputMessage();

auto output = tfs::net::make_output_message();
output->addByte(version >= 1076 ? 0x0B : 0x0A);
output->addString(message);
send(output);
Expand Down Expand Up @@ -94,7 +93,7 @@ void ProtocolLogin::getCharacterList(const std::string& accountName, const std::
uint32_t ticks = duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now().time_since_epoch()).count() /
AUTHENTICATOR_PERIOD;

auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();
if (!key.empty()) {
if (token.empty() || !(token == generateToken(key, ticks) || token == generateToken(key, ticks - 1) ||
token == generateToken(key, ticks + 1))) {
Expand Down
2 changes: 1 addition & 1 deletion src/protocolold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extern Game g_game;

void ProtocolOld::disconnectClient(const std::string& message)
{
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();
output->addByte(0x0A);
output->addString(message);
send(output);
Expand Down
4 changes: 2 additions & 2 deletions src/protocolstatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void ProtocolStatus::onRecvFirstMessage(NetworkMessage& msg)

void ProtocolStatus::sendStatusString()
{
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();

setRawMessages(true);

Expand Down Expand Up @@ -144,7 +144,7 @@ void ProtocolStatus::sendStatusString()

void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string& characterName)
{
auto output = OutputMessagePool::getOutputMessage();
auto output = tfs::net::make_output_message();

if (requestedInfo & REQUEST_BASIC_SERVER_INFO) {
output->addByte(0x10);
Expand Down

0 comments on commit 14ba662

Please sign in to comment.