mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
Simple workaround to fix vcmiserver shutdown procedure
At the moment, vcmilobby *requires* async writes in order to handle multiple connections with different speeds and at optimal performance, without hanging if one player is too slow and can't eat all data server sent to him at once. However server (and potentially - client) can not handle this mode and may shutdown either socket or entire asio service too early, before all writes are performed, leading to weird freeze on ending scenario where client would not receive notifications about end of game.
This commit is contained in:
parent
da9d82b697
commit
35954dc41b
@ -127,6 +127,11 @@ void NetworkConnection::onPacketReceived(const boost::system::error_code & ec, u
|
|||||||
startReceiving();
|
startReceiving();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetworkConnection::setAsyncWritesEnabled(bool on)
|
||||||
|
{
|
||||||
|
asyncWritesEnabled = on;
|
||||||
|
}
|
||||||
|
|
||||||
void NetworkConnection::sendPacket(const std::vector<std::byte> & message)
|
void NetworkConnection::sendPacket(const std::vector<std::byte> & message)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(writeMutex);
|
std::lock_guard<std::mutex> lock(writeMutex);
|
||||||
@ -134,14 +139,27 @@ void NetworkConnection::sendPacket(const std::vector<std::byte> & message)
|
|||||||
uint32_t messageSize = message.size();
|
uint32_t messageSize = message.size();
|
||||||
std::memcpy(headerVector.data(), &messageSize, sizeof(uint32_t));
|
std::memcpy(headerVector.data(), &messageSize, sizeof(uint32_t));
|
||||||
|
|
||||||
bool messageQueueEmpty = dataToSend.empty();
|
// At the moment, vcmilobby *requires* async writes in order to handle multiple connections with different speeds and at optimal performance
|
||||||
dataToSend.push_back(headerVector);
|
// However server (and potentially - client) can not handle this mode and may shutdown either socket or entire asio service too early, before all writes are performed
|
||||||
if (message.size() > 0)
|
if (asyncWritesEnabled)
|
||||||
dataToSend.push_back(message);
|
{
|
||||||
|
|
||||||
if (messageQueueEmpty)
|
bool messageQueueEmpty = dataToSend.empty();
|
||||||
doSendData();
|
dataToSend.push_back(headerVector);
|
||||||
//else - data sending loop is still active and still sending previous messages
|
if (message.size() > 0)
|
||||||
|
dataToSend.push_back(message);
|
||||||
|
|
||||||
|
if (messageQueueEmpty)
|
||||||
|
doSendData();
|
||||||
|
//else - data sending loop is still active and still sending previous messages
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boost::system::error_code ec;
|
||||||
|
boost::asio::write(*socket, boost::asio::buffer(headerVector), ec );
|
||||||
|
if (message.size() > 0)
|
||||||
|
boost::asio::write(*socket, boost::asio::buffer(message), ec );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkConnection::doSendData()
|
void NetworkConnection::doSendData()
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class NetworkConnection : public INetworkConnection, public std::enable_shared_from_this<NetworkConnection>
|
class NetworkConnection final : public INetworkConnection, public std::enable_shared_from_this<NetworkConnection>
|
||||||
{
|
{
|
||||||
static const int messageHeaderSize = sizeof(uint32_t);
|
static const int messageHeaderSize = sizeof(uint32_t);
|
||||||
static const int messageMaxSize = 64 * 1024 * 1024; // arbitrary size to prevent potential massive allocation if we receive garbage input
|
static const int messageMaxSize = 64 * 1024 * 1024; // arbitrary size to prevent potential massive allocation if we receive garbage input
|
||||||
@ -25,6 +25,7 @@ class NetworkConnection : public INetworkConnection, public std::enable_shared_f
|
|||||||
|
|
||||||
NetworkBuffer readBuffer;
|
NetworkBuffer readBuffer;
|
||||||
INetworkConnectionListener & listener;
|
INetworkConnectionListener & listener;
|
||||||
|
bool asyncWritesEnabled = false;
|
||||||
|
|
||||||
void heartbeat();
|
void heartbeat();
|
||||||
void onError(const std::string & message);
|
void onError(const std::string & message);
|
||||||
@ -42,6 +43,7 @@ public:
|
|||||||
void start();
|
void start();
|
||||||
void close() override;
|
void close() override;
|
||||||
void sendPacket(const std::vector<std::byte> & message) override;
|
void sendPacket(const std::vector<std::byte> & message) override;
|
||||||
|
void setAsyncWritesEnabled(bool on) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -17,6 +17,7 @@ class DLL_LINKAGE INetworkConnection : boost::noncopyable
|
|||||||
public:
|
public:
|
||||||
virtual ~INetworkConnection() = default;
|
virtual ~INetworkConnection() = default;
|
||||||
virtual void sendPacket(const std::vector<std::byte> & message) = 0;
|
virtual void sendPacket(const std::vector<std::byte> & message) = 0;
|
||||||
|
virtual void setAsyncWritesEnabled(bool on) = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -292,6 +292,7 @@ void LobbyServer::sendChatMessage(const NetworkConnectionPtr & target, const std
|
|||||||
|
|
||||||
void LobbyServer::onNewConnection(const NetworkConnectionPtr & connection)
|
void LobbyServer::onNewConnection(const NetworkConnectionPtr & connection)
|
||||||
{
|
{
|
||||||
|
connection->setAsyncWritesEnabled(true);
|
||||||
// no-op - waiting for incoming data
|
// no-op - waiting for incoming data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user