1
0
mirror of https://github.com/minetest/minetest.git synced 2025-07-06 09:50:23 +02:00

Rework packet receiving in ServerThread

Notably it tries to receive all queued packets
between server steps, not just one.
This commit is contained in:
sfan5
2019-11-14 17:38:15 +01:00
parent 97764600e2
commit c10952b574
5 changed files with 86 additions and 24 deletions

View File

@ -93,6 +93,15 @@ void *ServerThread::run()
{
BEGIN_DEBUG_EXCEPTION_HANDLER
/*
* The real business of the server happens on the ServerThread.
* How this works:
* AsyncRunStep() runs an actual server step as soon as enough time has
* passed (dedicated_server_loop keeps track of that).
* Receive() blocks at least(!) 30ms waiting for a packet (so this loop
* doesn't busy wait) and will process any remaining packets.
*/
m_server->AsyncRunStep(true);
while (!stopRequested()) {
@ -101,7 +110,6 @@ void *ServerThread::run()
m_server->Receive();
} catch (con::NoIncomingDataException &e) {
} catch (con::PeerNotFoundException &e) {
infostream<<"Server: PeerNotFoundException"<<std::endl;
} catch (ClientNotFoundException &e) {
@ -911,24 +919,43 @@ void Server::AsyncRunStep(bool initial_step)
void Server::Receive()
{
session_t peer_id = 0;
try {
NetworkPacket pkt;
m_con->Receive(&pkt);
peer_id = pkt.getPeerId();
ProcessData(&pkt);
} catch (const con::InvalidIncomingDataException &e) {
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
<< e.what() << std::endl;
} catch (const SerializationError &e) {
infostream << "Server::Receive(): SerializationError: what()="
<< e.what() << std::endl;
} catch (const ClientStateError &e) {
errorstream << "ProcessData: peer=" << peer_id << e.what() << std::endl;
DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect."
L"Try reconnecting or updating your client");
} catch (const con::PeerNotFoundException &e) {
// Do nothing
NetworkPacket pkt;
session_t peer_id;
bool first = true;
for (;;) {
pkt.clear();
peer_id = 0;
try {
/*
In the first iteration *wait* for a packet, afterwards process
all packets that are immediately available (no waiting).
*/
if (first) {
m_con->Receive(&pkt);
first = false;
} else {
if (!m_con->TryReceive(&pkt))
return;
}
peer_id = pkt.getPeerId();
ProcessData(&pkt);
} catch (const con::InvalidIncomingDataException &e) {
infostream << "Server::Receive(): InvalidIncomingDataException: what()="
<< e.what() << std::endl;
} catch (const SerializationError &e) {
infostream << "Server::Receive(): SerializationError: what()="
<< e.what() << std::endl;
} catch (const ClientStateError &e) {
errorstream << "ProcessData: peer=" << peer_id << " what()="
<< e.what() << std::endl;
DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect."
L"Try reconnecting or updating your client");
} catch (const con::PeerNotFoundException &e) {
// Do nothing
} catch (const con::NoIncomingDataException &e) {
return;
}
}
}
@ -3728,6 +3755,11 @@ void dedicated_server_loop(Server &server, bool &kill)
static thread_local const float profiler_print_interval =
g_settings->getFloat("profiler_print_interval");
/*
* The dedicated server loop only does time-keeping (in Server::step) and
* provides a way to main.cpp to kill the server externally (bool &kill).
*/
for(;;) {
// This is kind of a hack but can be done like this
// because server.step() is very light