Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor OutputMessagePool: Extracted into tfs::net namespace #4838

Merged
2 commits merged into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -452,7 +455,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 @@ -480,10 +483,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 @@ -3410,7 +3414,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
Loading