mirror of
https://github.com/minetest/minetest.git
synced 2024-11-23 16:13:46 +01:00
Rework client connecting and enable fallback address use
This commit is contained in:
parent
20692d54de
commit
2c390b5473
@ -97,7 +97,6 @@ void PacketCounter::print(std::ostream &o) const
|
|||||||
Client::Client(
|
Client::Client(
|
||||||
const char *playername,
|
const char *playername,
|
||||||
const std::string &password,
|
const std::string &password,
|
||||||
const std::string &address_name,
|
|
||||||
MapDrawControl &control,
|
MapDrawControl &control,
|
||||||
IWritableTextureSource *tsrc,
|
IWritableTextureSource *tsrc,
|
||||||
IWritableShaderSource *shsrc,
|
IWritableShaderSource *shsrc,
|
||||||
@ -106,7 +105,6 @@ Client::Client(
|
|||||||
ISoundManager *sound,
|
ISoundManager *sound,
|
||||||
MtEventManager *event,
|
MtEventManager *event,
|
||||||
RenderingEngine *rendering_engine,
|
RenderingEngine *rendering_engine,
|
||||||
bool ipv6,
|
|
||||||
GameUI *game_ui,
|
GameUI *game_ui,
|
||||||
ELoginRegister allow_login_or_register
|
ELoginRegister allow_login_or_register
|
||||||
):
|
):
|
||||||
@ -123,8 +121,6 @@ Client::Client(
|
|||||||
tsrc, this
|
tsrc, this
|
||||||
),
|
),
|
||||||
m_particle_manager(std::make_unique<ParticleManager>(&m_env)),
|
m_particle_manager(std::make_unique<ParticleManager>(&m_env)),
|
||||||
m_con(new con::Connection(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, ipv6, this)),
|
|
||||||
m_address_name(address_name),
|
|
||||||
m_allow_login_or_register(allow_login_or_register),
|
m_allow_login_or_register(allow_login_or_register),
|
||||||
m_server_ser_ver(SER_FMT_VER_INVALID),
|
m_server_ser_ver(SER_FMT_VER_INVALID),
|
||||||
m_last_chat_message_sent(time(NULL)),
|
m_last_chat_message_sent(time(NULL)),
|
||||||
@ -338,7 +334,8 @@ bool Client::isShutdown()
|
|||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
m_shutdown = true;
|
m_shutdown = true;
|
||||||
m_con->Disconnect();
|
if (m_con)
|
||||||
|
m_con->Disconnect();
|
||||||
|
|
||||||
deleteAuthData();
|
deleteAuthData();
|
||||||
|
|
||||||
@ -381,13 +378,32 @@ Client::~Client()
|
|||||||
m_sounds_client_to_server.clear();
|
m_sounds_client_to_server.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::connect(Address address, bool is_local_server)
|
void Client::connect(const Address &address, const std::string &address_name,
|
||||||
|
bool is_local_server)
|
||||||
{
|
{
|
||||||
initLocalMapSaving(address, m_address_name, is_local_server);
|
if (m_con) {
|
||||||
|
// can't do this if the connection has entered auth phase
|
||||||
|
sanity_check(m_state == LC_Created && m_proto_ver == 0);
|
||||||
|
infostream << "Client connection will be recreated" << std::endl;
|
||||||
|
|
||||||
|
m_access_denied = false;
|
||||||
|
m_access_denied_reconnect = false;
|
||||||
|
m_access_denied_reason.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_address_name = address_name;
|
||||||
|
m_con.reset(new con::Connection(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
|
||||||
|
address.isIPv6(), this));
|
||||||
|
|
||||||
|
infostream << "Connecting to server at ";
|
||||||
|
address.print(infostream);
|
||||||
|
infostream << std::endl;
|
||||||
|
|
||||||
// Since we use TryReceive() a timeout here would be ineffective anyway
|
// Since we use TryReceive() a timeout here would be ineffective anyway
|
||||||
m_con->SetTimeoutMs(0);
|
m_con->SetTimeoutMs(0);
|
||||||
m_con->Connect(address);
|
m_con->Connect(address);
|
||||||
|
|
||||||
|
initLocalMapSaving(address, m_address_name, is_local_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::step(float dtime)
|
void Client::step(float dtime)
|
||||||
@ -908,6 +924,10 @@ void Client::initLocalMapSaving(const Address &address,
|
|||||||
if (!g_settings->getBool("enable_local_map_saving") || is_local_server) {
|
if (!g_settings->getBool("enable_local_map_saving") || is_local_server) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (m_localdb) {
|
||||||
|
infostream << "Local map saving already running" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string world_path;
|
std::string world_path;
|
||||||
#define set_world_path(hostname) \
|
#define set_world_path(hostname) \
|
||||||
@ -935,6 +955,8 @@ void Client::ReceiveAll()
|
|||||||
NetworkPacket pkt;
|
NetworkPacket pkt;
|
||||||
u64 start_ms = porting::getTimeMs();
|
u64 start_ms = porting::getTimeMs();
|
||||||
const u64 budget = 10;
|
const u64 budget = 10;
|
||||||
|
|
||||||
|
FATAL_ERROR_IF(!m_con, "Networking not initialized");
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// Limit time even if there would be huge amounts of data to
|
// Limit time even if there would be huge amounts of data to
|
||||||
// process
|
// process
|
||||||
@ -1767,7 +1789,7 @@ ClientEvent *Client::getClientEvent()
|
|||||||
|
|
||||||
const Address Client::getServerAddress()
|
const Address Client::getServerAddress()
|
||||||
{
|
{
|
||||||
return m_con->GetPeerAddress(PEER_ID_SERVER);
|
return m_con ? m_con->GetPeerAddress(PEER_ID_SERVER) : Address();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Client::mediaReceiveProgress()
|
float Client::mediaReceiveProgress()
|
||||||
@ -1873,11 +1895,13 @@ void Client::afterContentReceived()
|
|||||||
|
|
||||||
float Client::getRTT()
|
float Client::getRTT()
|
||||||
{
|
{
|
||||||
|
assert(m_con);
|
||||||
return m_con->getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
|
return m_con->getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Client::getCurRate()
|
float Client::getCurRate()
|
||||||
{
|
{
|
||||||
|
assert(m_con);
|
||||||
return (m_con->getLocalStat(con::CUR_INC_RATE) +
|
return (m_con->getLocalStat(con::CUR_INC_RATE) +
|
||||||
m_con->getLocalStat(con::CUR_DL_RATE));
|
m_con->getLocalStat(con::CUR_DL_RATE));
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,6 @@ public:
|
|||||||
Client(
|
Client(
|
||||||
const char *playername,
|
const char *playername,
|
||||||
const std::string &password,
|
const std::string &password,
|
||||||
const std::string &address_name,
|
|
||||||
MapDrawControl &control,
|
MapDrawControl &control,
|
||||||
IWritableTextureSource *tsrc,
|
IWritableTextureSource *tsrc,
|
||||||
IWritableShaderSource *shsrc,
|
IWritableShaderSource *shsrc,
|
||||||
@ -131,7 +130,6 @@ public:
|
|||||||
ISoundManager *sound,
|
ISoundManager *sound,
|
||||||
MtEventManager *event,
|
MtEventManager *event,
|
||||||
RenderingEngine *rendering_engine,
|
RenderingEngine *rendering_engine,
|
||||||
bool ipv6,
|
|
||||||
GameUI *game_ui,
|
GameUI *game_ui,
|
||||||
ELoginRegister allow_login_or_register
|
ELoginRegister allow_login_or_register
|
||||||
);
|
);
|
||||||
@ -155,11 +153,8 @@ public:
|
|||||||
|
|
||||||
bool isShutdown();
|
bool isShutdown();
|
||||||
|
|
||||||
/*
|
void connect(const Address &address, const std::string &address_name,
|
||||||
The name of the local player should already be set when
|
bool is_local_server);
|
||||||
calling this, as it is sent in the initialization.
|
|
||||||
*/
|
|
||||||
void connect(Address address, bool is_local_server);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Stuff that references the environment is valid only as
|
Stuff that references the environment is valid only as
|
||||||
@ -351,7 +346,7 @@ public:
|
|||||||
bool activeObjectsReceived() const
|
bool activeObjectsReceived() const
|
||||||
{ return m_activeobjects_received; }
|
{ return m_activeobjects_received; }
|
||||||
|
|
||||||
u16 getProtoVersion()
|
u16 getProtoVersion() const
|
||||||
{ return m_proto_ver; }
|
{ return m_proto_ver; }
|
||||||
|
|
||||||
bool m_simple_singleplayer_mode;
|
bool m_simple_singleplayer_mode;
|
||||||
@ -363,6 +358,10 @@ public:
|
|||||||
|
|
||||||
float getRTT();
|
float getRTT();
|
||||||
float getCurRate();
|
float getCurRate();
|
||||||
|
// has the server ever replied to us, used for connection retry/fallback
|
||||||
|
bool hasServerReplied() const {
|
||||||
|
return getProtoVersion() != 0; // (set in TOCLIENT_HELLO)
|
||||||
|
}
|
||||||
|
|
||||||
Minimap* getMinimap() { return m_minimap; }
|
Minimap* getMinimap() { return m_minimap; }
|
||||||
void setCamera(Camera* camera) { m_camera = camera; }
|
void setCamera(Camera* camera) { m_camera = camera; }
|
||||||
@ -415,8 +414,10 @@ public:
|
|||||||
|
|
||||||
void showMinimap(bool show = true);
|
void showMinimap(bool show = true);
|
||||||
|
|
||||||
|
// IP and port we're connected to
|
||||||
const Address getServerAddress();
|
const Address getServerAddress();
|
||||||
|
|
||||||
|
// Hostname of the connected server (but can also be a numerical IP)
|
||||||
const std::string &getAddressName() const
|
const std::string &getAddressName() const
|
||||||
{
|
{
|
||||||
return m_address_name;
|
return m_address_name;
|
||||||
|
@ -1613,13 +1613,15 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||||||
*connect_ok = false; // Let's not be overly optimistic
|
*connect_ok = false; // Let's not be overly optimistic
|
||||||
*connection_aborted = false;
|
*connection_aborted = false;
|
||||||
bool local_server_mode = false;
|
bool local_server_mode = false;
|
||||||
|
const auto &address_name = start_data.address;
|
||||||
|
|
||||||
showOverlayMessage(N_("Resolving address..."), 0, 15);
|
showOverlayMessage(N_("Resolving address..."), 0, 15);
|
||||||
|
|
||||||
Address connect_address(0, 0, 0, 0, start_data.socket_port);
|
Address connect_address(0, 0, 0, 0, start_data.socket_port);
|
||||||
|
Address fallback_address;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connect_address.Resolve(start_data.address.c_str());
|
connect_address.Resolve(address_name.c_str(), &fallback_address);
|
||||||
|
|
||||||
if (connect_address.isAny()) {
|
if (connect_address.isAny()) {
|
||||||
// replace with localhost IP
|
// replace with localhost IP
|
||||||
@ -1639,45 +1641,58 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect_address.isIPv6() && !g_settings->getBool("enable_ipv6")) {
|
// this shouldn't normally happen since Address::Resolve() checks for enable_ipv6
|
||||||
|
if (g_settings->getBool("enable_ipv6")) {
|
||||||
|
// empty
|
||||||
|
} else if (connect_address.isIPv6()) {
|
||||||
*error_message = fmtgettext("Unable to connect to %s because IPv6 is disabled", connect_address.serializeString().c_str());
|
*error_message = fmtgettext("Unable to connect to %s because IPv6 is disabled", connect_address.serializeString().c_str());
|
||||||
errorstream << *error_message << std::endl;
|
errorstream << *error_message << std::endl;
|
||||||
return false;
|
return false;
|
||||||
|
} else if (fallback_address.isIPv6()) {
|
||||||
|
fallback_address = Address();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fallback_address.setPort(connect_address.getPort());
|
||||||
|
if (fallback_address.isValid()) {
|
||||||
|
infostream << "Resolved two addresses for \"" << address_name
|
||||||
|
<< "\" isIPv6[0]=" << connect_address.isIPv6()
|
||||||
|
<< " isIPv6[1]=" << fallback_address.isIPv6() << std::endl;
|
||||||
|
} else {
|
||||||
|
infostream << "Resolved one address for \"" << address_name
|
||||||
|
<< "\" isIPv6=" << connect_address.isIPv6() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client = new Client(start_data.name.c_str(),
|
client = new Client(start_data.name.c_str(),
|
||||||
start_data.password, start_data.address,
|
start_data.password,
|
||||||
*draw_control, texture_src, shader_src,
|
*draw_control, texture_src, shader_src,
|
||||||
itemdef_manager, nodedef_manager, sound_manager.get(), eventmgr,
|
itemdef_manager, nodedef_manager, sound_manager.get(), eventmgr,
|
||||||
m_rendering_engine, connect_address.isIPv6(), m_game_ui.get(),
|
m_rendering_engine, m_game_ui.get(),
|
||||||
start_data.allow_login_or_register);
|
start_data.allow_login_or_register);
|
||||||
client->migrateModStorage();
|
|
||||||
} catch (const BaseException &e) {
|
} catch (const BaseException &e) {
|
||||||
*error_message = fmtgettext("Error creating client: %s", e.what());
|
*error_message = fmtgettext("Error creating client: %s", e.what());
|
||||||
errorstream << *error_message << std::endl;
|
errorstream << *error_message << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client->migrateModStorage();
|
||||||
client->m_simple_singleplayer_mode = simple_singleplayer_mode;
|
client->m_simple_singleplayer_mode = simple_singleplayer_mode;
|
||||||
|
|
||||||
infostream << "Connecting to server at ";
|
|
||||||
connect_address.print(infostream);
|
|
||||||
infostream << std::endl;
|
|
||||||
|
|
||||||
client->connect(connect_address,
|
|
||||||
simple_singleplayer_mode || local_server_mode);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Wait for server to accept connection
|
Wait for server to accept connection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
client->connect(connect_address, address_name,
|
||||||
|
simple_singleplayer_mode || local_server_mode);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
input->clear();
|
input->clear();
|
||||||
|
|
||||||
FpsControl fps_control;
|
FpsControl fps_control;
|
||||||
f32 dtime;
|
f32 dtime;
|
||||||
f32 wait_time = 0; // in seconds
|
f32 wait_time = 0; // in seconds
|
||||||
|
bool did_fallback = false;
|
||||||
|
|
||||||
fps_control.reset();
|
fps_control.reset();
|
||||||
|
|
||||||
@ -1712,8 +1727,15 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wait_time += dtime;
|
wait_time += dtime;
|
||||||
// Only time out if we aren't waiting for the server we started
|
if (local_server_mode) {
|
||||||
if (!start_data.address.empty() && wait_time > 10) {
|
// never time out
|
||||||
|
} else if (wait_time > GAME_FALLBACK_TIMEOUT && !did_fallback) {
|
||||||
|
if (!client->hasServerReplied() && fallback_address.isValid()) {
|
||||||
|
client->connect(fallback_address, address_name,
|
||||||
|
simple_singleplayer_mode || local_server_mode);
|
||||||
|
}
|
||||||
|
did_fallback = true;
|
||||||
|
} else if (wait_time > GAME_CONNECTION_TIMEOUT) {
|
||||||
*error_message = gettext("Connection timed out.");
|
*error_message = gettext("Connection timed out.");
|
||||||
errorstream << *error_message << std::endl;
|
errorstream << *error_message << std::endl;
|
||||||
break;
|
break;
|
||||||
@ -1723,8 +1745,7 @@ bool Game::connectToServer(const GameStartData &start_data,
|
|||||||
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
||||||
}
|
}
|
||||||
} catch (con::PeerNotFoundException &e) {
|
} catch (con::PeerNotFoundException &e) {
|
||||||
// TODO: Should something be done here? At least an info/error
|
warningstream << "This should not happen. Please report a bug." << std::endl;
|
||||||
// message?
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ struct CameraOrientation {
|
|||||||
f32 camera_pitch; // "up/down"
|
f32 camera_pitch; // "up/down"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GAME_FALLBACK_TIMEOUT 1.8f
|
||||||
|
#define GAME_CONNECTION_TIMEOUT 10.0f
|
||||||
|
|
||||||
void the_game(bool *kill,
|
void the_game(bool *kill,
|
||||||
InputHandler *input,
|
InputHandler *input,
|
||||||
|
@ -163,6 +163,7 @@ void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
|
|||||||
|
|
||||||
m_state = LC_Init;
|
m_state = LC_Init;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
|
void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
|
||||||
{
|
{
|
||||||
deleteAuthData();
|
deleteAuthData();
|
||||||
|
Loading…
Reference in New Issue
Block a user