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

[no squash] Networking improvements / hardening #14217

Merged
merged 13 commits into from
Jan 17, 2024
59 changes: 52 additions & 7 deletions src/clientiface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,31 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/srp.h"
#include "face_position_cache.h"

static std::string string_sanitize_ascii(const std::string &s, u32 max_length)
{
std::string out;
for (char c : s) {
if (out.size() >= max_length)
break;
if (c > 32 && c < 127)
out.push_back(c);
}
return out;
}

const char *ClientInterface::statenames[] = {
"Invalid",
"Disconnecting",
"Denied",
"Created",
"AwaitingInit2",
"HelloSent",
"AwaitingInit2",
"InitDone",
"DefinitionsSent",
"Active",
"SudoMode",
};



std::string ClientInterface::state2Name(ClientState state)
{
return statenames[state];
Expand Down Expand Up @@ -639,16 +649,23 @@ void RemoteClient::resetChosenMech()
chosen_mech = AUTH_MECHANISM_NONE;
}

u64 RemoteClient::uptime() const
void RemoteClient::setVersionInfo(u8 major, u8 minor, u8 patch, const std::string &full)
{
return porting::getTimeS() - m_connection_time;
m_version_major = major;
m_version_minor = minor;
m_version_patch = patch;
m_full_version = string_sanitize_ascii(full, 64);
}

void RemoteClient::setLangCode(const std::string &code)
{
m_lang_code = string_sanitize_ascii(code, 12);
}

ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
:
m_con(con),
m_env(NULL),
m_print_info_timer(0.0f)
m_env(nullptr)
{

}
Expand Down Expand Up @@ -706,6 +723,34 @@ void ClientInterface::step(float dtime)
m_print_info_timer = 0.0f;
UpdatePlayerList();
}

m_check_linger_timer += dtime;
if (m_check_linger_timer < 1.0f)
return;
m_check_linger_timer = 0;

RecursiveMutexAutoLock clientslock(m_clients_mutex);
for (const auto &it : m_clients) {
auto state = it.second->getState();
if (state >= CS_HelloSent)
continue;
if (it.second->uptime() <= LINGER_TIMEOUT)
continue;
// CS_Created means nobody has even noticed the client is there
// (this is before on_prejoinplayer runs)
// CS_Invalid should not happen
// -> log those as warning, the rest as info
std::ostream &os = state == CS_Created || state == CS_Invalid ?
warningstream : infostream;
try {
Address addr = m_con->GetPeerAddress(it.second->peer_id);
os << "Disconnecting lingering client from "
<< addr.serializeString() << " (state="
<< state2Name(state) << ")" << std::endl;
m_con->DisconnectPeer(it.second->peer_id);
} catch (con::PeerNotFoundException &e) {
}
}
}

void ClientInterface::UpdatePlayerList()
Expand Down
19 changes: 8 additions & 11 deletions src/clientiface.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ enum ClientState
CS_Disconnecting,
CS_Denied,
CS_Created,
CS_AwaitingInit2,
CS_HelloSent,
CS_AwaitingInit2,
CS_InitDone,
CS_DefinitionsSent,
CS_Active,
Expand Down Expand Up @@ -329,24 +329,18 @@ class RemoteClient
{ serialization_version = m_pending_serialization_version; }

/* get uptime */
u64 uptime() const;
u64 uptime() const { return porting::getTimeS() - m_connection_time; }

/* set version information */
void setVersionInfo(u8 major, u8 minor, u8 patch, const std::string &full)
{
m_version_major = major;
m_version_minor = minor;
m_version_patch = patch;
m_full_version = full;
}
void setVersionInfo(u8 major, u8 minor, u8 patch, const std::string &full);

/* read version information */
u8 getMajor() const { return m_version_major; }
u8 getMinor() const { return m_version_minor; }
u8 getPatch() const { return m_version_patch; }
const std::string &getFullVer() const { return m_full_version; }

void setLangCode(const std::string &code) { m_lang_code = code; }
void setLangCode(const std::string &code);
const std::string &getLangCode() const { return m_lang_code; }

void setCachedAddress(const Address &addr) { m_addr = addr; }
Expand Down Expand Up @@ -550,7 +544,10 @@ class ClientInterface {
// Environment
ServerEnvironment *m_env;

float m_print_info_timer;
float m_print_info_timer = 0;
float m_check_linger_timer = 0;

static const char *statenames[];

static constexpr int LINGER_TIMEOUT = 10;
};
5 changes: 0 additions & 5 deletions src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#define CONNECTION_TIMEOUT 30

#define RESEND_TIMEOUT_MIN 0.1
#define RESEND_TIMEOUT_MAX 3.0
// resend_timeout = avg_rtt * this
#define RESEND_TIMEOUT_FACTOR 4

/*
Server
*/
Expand Down