1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-27 17:28:41 +00:00

Merge remote-tracking branch 'upstream/master' into Visuals-Vol-2

This commit is contained in:
Gefüllte Taubenbrust 2024-09-25 20:53:09 +02:00
commit 71e648a776
647 changed files with 60434 additions and 37195 deletions

View file

@ -1,10 +1,11 @@
set(common_network_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/address.cpp
${CMAKE_CURRENT_SOURCE_DIR}/connection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/connectionthreads.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mtp/impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mtp/threads.cpp
${CMAKE_CURRENT_SOURCE_DIR}/networkpacket.cpp
${CMAKE_CURRENT_SOURCE_DIR}/serverpackethandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/serveropcodes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/serverpackethandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/socket.cpp
PARENT_SCOPE
)

View file

@ -81,7 +81,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_MOVE_PLAYER", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_MovePlayer }, // 0x34
{ "TOCLIENT_ACCESS_DENIED_LEGACY", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_AccessDenied }, // 0x35
{ "TOCLIENT_FOV", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Fov }, // 0x36
{ "TOCLIENT_DEATHSCREEN", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreen }, // 0x37
{ "TOCLIENT_DEATHSCREEN_LEGACY", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_DeathScreenLegacy }, // 0x37
{ "TOCLIENT_MEDIA", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Media }, // 0x38
null_command_handler,
{ "TOCLIENT_NODEDEF", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_NodeDef }, // 0x3a
@ -198,7 +198,7 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] =
{ "TOSERVER_DAMAGE", 0, true }, // 0x35
null_command_factory, // 0x36
{ "TOSERVER_PLAYERITEM", 0, true }, // 0x37
{ "TOSERVER_RESPAWN", 0, true }, // 0x38
{ "TOSERVER_RESPAWN_LEGACY", 0, true }, // 0x38
{ "TOSERVER_INTERACT", 0, true }, // 0x39
{ "TOSERVER_REMOVED_SOUNDS", 2, true }, // 0x3a
{ "TOSERVER_NODEMETA_FIELDS", 0, true }, // 0x3b

View file

@ -48,6 +48,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "particles.h"
#include <memory>
const char *accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
N_("Invalid password"),
N_("Your client sent something the server didn't expect. Try reconnecting or updating your client."),
N_("The server is running in singleplayer mode. You cannot connect."),
N_("Your client's version is not supported.\nPlease contact the server administrator."),
N_("Player name contains disallowed characters"),
N_("Player name not allowed"),
N_("Too many users"),
N_("Empty passwords are disallowed. Set a password and try again."),
N_("Another client is connected with this name. If your client closed unexpectedly, try again in a minute."),
N_("Internal server error"),
"",
N_("Server shutting down"),
N_("The server has experienced an internal error. You will now be disconnected.")
};
void Client::handleCommand_Deprecated(NetworkPacket* pkt)
{
infostream << "Got deprecated command "
@ -62,11 +78,11 @@ void Client::handleCommand_Hello(NetworkPacket* pkt)
u8 serialization_ver;
u16 proto_ver;
u16 compression_mode;
u16 unused_compression_mode;
u32 auth_mechs;
std::string username_legacy; // for case insensitivity
*pkt >> serialization_ver >> compression_mode >> proto_ver
>> auth_mechs >> username_legacy;
std::string unused;
*pkt >> serialization_ver >> unused_compression_mode >> proto_ver
>> auth_mechs >> unused;
// Chose an auth method we support
AuthMechanism chosen_auth_mechanism = choseAuthMech(auth_mechs);
@ -75,7 +91,6 @@ void Client::handleCommand_Hello(NetworkPacket* pkt)
<< "serialization_ver=" << (u32)serialization_ver
<< ", auth_mechs=" << auth_mechs
<< ", proto_ver=" << proto_ver
<< ", compression_mode=" << compression_mode
<< ". Doing auth with mech " << chosen_auth_mechanism << std::endl;
if (!ser_ver_supported(serialization_ver)) {
@ -87,10 +102,6 @@ void Client::handleCommand_Hello(NetworkPacket* pkt)
m_server_ser_ver = serialization_ver;
m_proto_ver = proto_ver;
//TODO verify that username_legacy matches sent username, only
// differs in casing (make both uppercase and compare)
// This is only necessary though when we actually want to add casing support
if (m_chosen_auth_mech != AUTH_MECHANISM_NONE) {
// we received a TOCLIENT_HELLO while auth was already going on
errorstream << "Client: TOCLIENT_HELLO while auth was already going on"
@ -193,7 +204,6 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
// to be processed even if the serialization format has
// not been agreed yet, the same as TOCLIENT_INIT.
m_access_denied = true;
m_access_denied_reason = "Unknown";
if (pkt->getCommand() != TOCLIENT_ACCESS_DENIED) {
// Legacy code from 0.4.12 and older but is still used
@ -212,29 +222,23 @@ void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
u8 denyCode;
*pkt >> denyCode;
if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN ||
denyCode == SERVER_ACCESSDENIED_CRASH) {
if (pkt->getRemainingBytes() > 0)
*pkt >> m_access_denied_reason;
if (m_access_denied_reason.empty())
m_access_denied_reason = accessDeniedStrings[denyCode];
if (m_access_denied_reason.empty()) {
if (denyCode >= SERVER_ACCESSDENIED_MAX) {
m_access_denied_reason = gettext("Unknown disconnect reason.");
} else if (denyCode != SERVER_ACCESSDENIED_CUSTOM_STRING) {
m_access_denied_reason = gettext(accessDeniedStrings[denyCode]);
}
}
if (denyCode == SERVER_ACCESSDENIED_TOO_MANY_USERS) {
m_access_denied_reconnect = true;
} else if (pkt->getRemainingBytes() > 0) {
u8 reconnect;
*pkt >> reconnect;
m_access_denied_reconnect = reconnect & 1;
} else if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
*pkt >> m_access_denied_reason;
} else if (denyCode == SERVER_ACCESSDENIED_TOO_MANY_USERS) {
m_access_denied_reason = accessDeniedStrings[denyCode];
m_access_denied_reconnect = true;
} else if (denyCode < SERVER_ACCESSDENIED_MAX) {
m_access_denied_reason = accessDeniedStrings[denyCode];
} else {
// Allow us to add new error messages to the
// protocol without raising the protocol version, if we want to.
// Until then (which may be never), this is outside
// of the defined protocol.
*pkt >> m_access_denied_reason;
if (m_access_denied_reason.empty())
m_access_denied_reason = "Unknown";
}
}
@ -471,6 +475,8 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
for (u16 i = 0; i < removed_count; i++) {
*pkt >> id;
m_env.removeActiveObject(id);
// Object-attached sounds MUST NOT be removed here because they might
// have started to play immediately before the entity was removed.
}
// Read added objects
@ -647,20 +653,10 @@ void Client::handleCommand_MovePlayerRel(NetworkPacket *pkt)
player->addPosition(added_pos);
}
void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
void Client::handleCommand_DeathScreenLegacy(NetworkPacket* pkt)
{
bool set_camera_point_target;
v3f camera_point_target;
*pkt >> set_camera_point_target;
*pkt >> camera_point_target;
ClientEvent *event = new ClientEvent();
event->type = CE_DEATHSCREEN;
event->deathscreen.set_camera_point_target = set_camera_point_target;
event->deathscreen.camera_point_target_x = camera_point_target.X;
event->deathscreen.camera_point_target_y = camera_point_target.Y;
event->deathscreen.camera_point_target_z = camera_point_target.Z;
event->type = CE_DEATHSCREEN_LEGACY;
m_client_event_queue.push(event);
}
@ -1470,6 +1466,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
f32 density;
video::SColor color_bright;
video::SColor color_ambient;
video::SColor color_shadow = video::SColor(255, 204, 204, 204);
f32 height;
f32 thickness;
v2f speed;
@ -1477,6 +1474,10 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
*pkt >> density >> color_bright >> color_ambient
>> height >> thickness >> speed;
if (pkt->getRemainingBytes() >= 4) {
*pkt >> color_shadow;
}
ClientEvent *event = new ClientEvent();
event->type = CE_CLOUD_PARAMS;
event->cloud_params.density = density;
@ -1485,6 +1486,7 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
// we avoid using new() and delete() for no good reason
event->cloud_params.color_bright = color_bright.color;
event->cloud_params.color_ambient = color_ambient.color;
event->cloud_params.color_shadow = color_shadow.color;
event->cloud_params.height = height;
event->cloud_params.thickness = thickness;
// same here: deconstruct to skip constructor
@ -1817,4 +1819,6 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
*pkt >> lighting.volumetric_light_strength;
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.artificial_light_color;
if (pkt->getRemainingBytes() >= 4)
*pkt >> lighting.shadow_tint;
}

File diff suppressed because it is too large Load diff

View file

@ -1,44 +1,26 @@
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Minetest
// SPDX-License-Identifier: LGPL-2.1-or-later
#pragma once
#include "irrlichttypes.h"
#include "peerhandler.h"
#include "socket.h"
#include "constants.h"
#include "util/pointer.h"
#include "util/container.h"
#include "util/numeric.h"
#include "porting.h"
#include "networkprotocol.h"
#include <iostream>
#include <vector>
#include <map>
#include "networkprotocol.h" // session_t
class NetworkPacket;
class PeerHandler;
namespace con
{
class ConnectionReceiveThread;
class ConnectionSendThread;
enum rtt_stat_type {
MIN_RTT,
MAX_RTT,
AVG_RTT,
MIN_JITTER,
MAX_JITTER,
AVG_JITTER
};
enum rate_stat_type {
CUR_DL_RATE,
@ -49,295 +31,43 @@ enum rate_stat_type {
AVG_LOSS_RATE,
};
class Peer;
// FIXME: Peer refcounting should generally be replaced by std::shared_ptr
class PeerHelper
{
class IPeer {
public:
PeerHelper() = default;
inline PeerHelper(Peer *peer) { *this = peer; }
~PeerHelper();
// Unique id of the peer
const session_t id;
PeerHelper& operator=(Peer *peer);
inline Peer* operator->() const { return m_peer; }
inline Peer* operator&() const { return m_peer; }
inline bool operator!() { return !m_peer; }
inline bool operator!=(std::nullptr_t) { return !!m_peer; }
private:
Peer *m_peer = nullptr;
};
/*
Connection
*/
enum ConnectionEventType {
CONNEVENT_NONE,
CONNEVENT_DATA_RECEIVED,
CONNEVENT_PEER_ADDED,
CONNEVENT_PEER_REMOVED,
CONNEVENT_BIND_FAILED,
};
struct ConnectionEvent;
typedef std::shared_ptr<ConnectionEvent> ConnectionEventPtr;
// This is very similar to ConnectionCommand
struct ConnectionEvent
{
const ConnectionEventType type;
session_t peer_id = 0;
Buffer<u8> data;
bool timeout = false;
Address address;
// We don't want to copy "data"
DISABLE_CLASS_COPY(ConnectionEvent);
static ConnectionEventPtr create(ConnectionEventType type);
static ConnectionEventPtr dataReceived(session_t peer_id, const Buffer<u8> &data);
static ConnectionEventPtr peerAdded(session_t peer_id, Address address);
static ConnectionEventPtr peerRemoved(session_t peer_id, bool is_timeout, Address address);
static ConnectionEventPtr bindFailed();
const char *describe() const;
private:
ConnectionEvent(ConnectionEventType type_) :
type(type_) {}
};
struct ConnectionCommand;
typedef std::shared_ptr<ConnectionCommand> ConnectionCommandPtr;
struct BufferedPacket;
typedef std::shared_ptr<BufferedPacket> BufferedPacketPtr;
class Connection;
class PeerHandler;
class Peer {
public:
friend class PeerHelper;
virtual ~Peer() {
MutexAutoLock usage_lock(m_exclusive_access_mutex);
FATAL_ERROR_IF(m_usage != 0, "Reference counting failure");
}
// Unique id of the peer
const session_t id;
void Drop();
virtual void PutReliableSendCommand(ConnectionCommandPtr &c,
unsigned int max_packet_size) {};
virtual const Address &getAddress() const = 0;
bool isPendingDeletion() const {
MutexAutoLock lock(m_exclusive_access_mutex);
return m_pending_deletion;
}
void ResetTimeout() {
MutexAutoLock lock(m_exclusive_access_mutex);
m_timeout_counter = 0;
}
bool isHalfOpen() const {
MutexAutoLock lock(m_exclusive_access_mutex);
return m_half_open;
}
void SetFullyOpen() {
MutexAutoLock lock(m_exclusive_access_mutex);
m_half_open = false;
}
virtual bool isTimedOut(float timeout, std::string &reason);
unsigned int m_increment_packets_remaining = 0;
virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
virtual SharedBuffer<u8> addSplitPacket(u8 channel, BufferedPacketPtr &toadd,
bool reliable)
{
FATAL_ERROR("unimplemented in abstract class");
}
virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
virtual float getStat(rtt_stat_type type) const {
switch (type) {
case MIN_RTT:
return m_rtt.min_rtt;
case MAX_RTT:
return m_rtt.max_rtt;
case AVG_RTT:
return m_rtt.avg_rtt;
case MIN_JITTER:
return m_rtt.jitter_min;
case MAX_JITTER:
return m_rtt.jitter_max;
case AVG_JITTER:
return m_rtt.jitter_avg;
}
return -1;
}
protected:
Peer(session_t id, const Address &address, Connection *connection) :
id(id),
m_connection(connection),
address(address),
m_last_timeout_check(porting::getTimeMs())
{
}
virtual void reportRTT(float rtt) {};
void RTTStatistics(float rtt,
const std::string &profiler_id = "",
unsigned int num_samples = 1000);
bool IncUseCount();
void DecUseCount();
mutable std::mutex m_exclusive_access_mutex;
bool m_pending_deletion = false;
Connection *m_connection;
// Address of the peer
Address address;
// Ping timer
float m_ping_timer = 0.0f;
private:
struct rttstats {
float jitter_min = FLT_MAX;
float jitter_max = 0.0f;
float jitter_avg = -1.0f;
float min_rtt = FLT_MAX;
float max_rtt = 0.0f;
float avg_rtt = -1.0f;
};
rttstats m_rtt;
float m_last_rtt = -1.0f;
/*
Until the peer has communicated with us using their assigned peer id
the connection is considered half-open.
During this time we inhibit re-sending any reliables or pings. This
is to avoid spending too many resources on a potential DoS attack
and to make sure Minetest servers are not useful for UDP amplificiation.
*/
bool m_half_open = true;
// current usage count
unsigned int m_usage = 0;
// Seconds from last receive
float m_timeout_counter = 0.0f;
u64 m_last_timeout_check;
};
class UDPPeer;
class Connection
{
public:
friend class ConnectionSendThread;
friend class ConnectionReceiveThread;
Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
PeerHandler *peerhandler);
~Connection();
/* Interface */
ConnectionEventPtr waitEvent(u32 timeout_ms);
void putCommand(ConnectionCommandPtr c);
void SetTimeoutMs(u32 timeout) { m_bc_receive_timeout = timeout; }
void Serve(Address bind_addr);
void Connect(Address address);
bool Connected();
void Disconnect();
bool ReceiveTimeoutMs(NetworkPacket *pkt, u32 timeout_ms);
void Receive(NetworkPacket *pkt);
bool TryReceive(NetworkPacket *pkt);
void Send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
session_t GetPeerID() const { return m_peer_id; }
Address GetPeerAddress(session_t peer_id);
float getPeerStat(session_t peer_id, rtt_stat_type type);
float getLocalStat(rate_stat_type type);
u32 GetProtocolID() const { return m_protocol_id; };
const std::string getDesc();
void DisconnectPeer(session_t peer_id);
virtual const Address &getAddress() const = 0;
protected:
PeerHelper getPeerNoEx(session_t peer_id);
session_t lookupPeer(const Address& sender);
session_t createPeer(const Address& sender, int fd);
UDPPeer* createServerPeer(const Address& sender);
bool deletePeer(session_t peer_id, bool timeout);
void SetPeerID(session_t id) { m_peer_id = id; }
void doResendOne(session_t peer_id);
void sendAck(session_t peer_id, u8 channelnum, u16 seqnum);
std::vector<session_t> getPeerIDs()
{
MutexAutoLock peerlock(m_peers_mutex);
return m_peer_ids;
}
u32 getActiveCount();
UDPSocket m_udpSocket;
// Command queue: user -> SendThread
MutexedQueue<ConnectionCommandPtr> m_command_queue;
void putEvent(ConnectionEventPtr e);
void TriggerSend();
bool ConnectedToServer()
{
return getPeerNoEx(PEER_ID_SERVER) != nullptr;
}
private:
// Event queue: ReceiveThread -> user
MutexedQueue<ConnectionEventPtr> m_event_queue;
session_t m_peer_id = 0;
u32 m_protocol_id;
std::map<session_t, Peer *> m_peers;
std::vector<session_t> m_peer_ids;
std::mutex m_peers_mutex;
std::unique_ptr<ConnectionSendThread> m_sendThread;
std::unique_ptr<ConnectionReceiveThread> m_receiveThread;
mutable std::mutex m_info_mutex;
// Backwards compatibility
PeerHandler *m_bc_peerhandler;
u32 m_bc_receive_timeout = 0;
bool m_shutting_down = false;
IPeer(session_t id) : id(id) {}
~IPeer() {}
};
class IConnection
{
public:
virtual ~IConnection() = default;
virtual void Serve(Address bind_addr) = 0;
virtual void Connect(Address address) = 0;
virtual bool Connected() = 0;
virtual void Disconnect() = 0;
virtual void DisconnectPeer(session_t peer_id) = 0;
virtual bool ReceiveTimeoutMs(NetworkPacket *pkt, u32 timeout_ms) = 0;
bool TryReceive(NetworkPacket *pkt) {
return ReceiveTimeoutMs(pkt, 0);
}
virtual void Send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable) = 0;
virtual session_t GetPeerID() const = 0;
virtual Address GetPeerAddress(session_t peer_id) = 0;
virtual float getPeerStat(session_t peer_id, rtt_stat_type type) = 0;
virtual float getLocalStat(rate_stat_type type) = 0;
};
// MTP = Minetest Protocol
IConnection *createMTP(float timeout, bool ipv6, PeerHandler *handler);
} // namespace

1674
src/network/mtp/impl.cpp Normal file

File diff suppressed because it is too large Load diff

322
src/network/mtp/impl.h Normal file
View file

@ -0,0 +1,322 @@
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "network/connection.h"
#include "network/socket.h"
#include "constants.h"
#include "util/pointer.h"
#include "util/container.h"
#include "util/numeric.h"
#include "porting.h"
#include "network/networkprotocol.h"
#include <iostream>
#include <vector>
#include <map>
namespace con
{
class ConnectionReceiveThread;
class ConnectionSendThread;
class Peer;
// FIXME: Peer refcounting should generally be replaced by std::shared_ptr
class PeerHelper
{
public:
PeerHelper() = default;
inline PeerHelper(Peer *peer) { *this = peer; }
~PeerHelper();
PeerHelper& operator=(Peer *peer);
inline Peer* operator->() const { return m_peer; }
inline Peer* operator&() const { return m_peer; }
inline bool operator!() { return !m_peer; }
inline bool operator!=(std::nullptr_t) { return !!m_peer; }
private:
Peer *m_peer = nullptr;
};
/*
Connection
*/
enum ConnectionEventType {
CONNEVENT_NONE,
CONNEVENT_DATA_RECEIVED,
CONNEVENT_PEER_ADDED,
CONNEVENT_PEER_REMOVED,
CONNEVENT_BIND_FAILED,
};
struct ConnectionEvent;
typedef std::shared_ptr<ConnectionEvent> ConnectionEventPtr;
// This is very similar to ConnectionCommand
struct ConnectionEvent
{
const ConnectionEventType type;
session_t peer_id = 0;
Buffer<u8> data;
bool timeout = false;
Address address;
// We don't want to copy "data"
DISABLE_CLASS_COPY(ConnectionEvent);
static ConnectionEventPtr create(ConnectionEventType type);
static ConnectionEventPtr dataReceived(session_t peer_id, const Buffer<u8> &data);
static ConnectionEventPtr peerAdded(session_t peer_id, Address address);
static ConnectionEventPtr peerRemoved(session_t peer_id, bool is_timeout, Address address);
static ConnectionEventPtr bindFailed();
const char *describe() const;
private:
ConnectionEvent(ConnectionEventType type_) :
type(type_) {}
};
struct ConnectionCommand;
typedef std::shared_ptr<ConnectionCommand> ConnectionCommandPtr;
struct BufferedPacket;
typedef std::shared_ptr<BufferedPacket> BufferedPacketPtr;
class Connection;
class PeerHandler;
class Peer : public IPeer {
public:
friend class PeerHelper;
virtual ~Peer() {
MutexAutoLock usage_lock(m_exclusive_access_mutex);
FATAL_ERROR_IF(m_usage != 0, "Reference counting failure");
}
void Drop();
virtual void PutReliableSendCommand(ConnectionCommandPtr &c,
unsigned int max_packet_size) {};
bool isPendingDeletion() const {
MutexAutoLock lock(m_exclusive_access_mutex);
return m_pending_deletion;
}
void ResetTimeout() {
MutexAutoLock lock(m_exclusive_access_mutex);
m_timeout_counter = 0;
}
bool isHalfOpen() const {
MutexAutoLock lock(m_exclusive_access_mutex);
return m_half_open;
}
void SetFullyOpen() {
MutexAutoLock lock(m_exclusive_access_mutex);
m_half_open = false;
}
virtual bool isTimedOut(float timeout, std::string &reason);
unsigned int m_increment_packets_remaining = 0;
virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
virtual SharedBuffer<u8> addSplitPacket(u8 channel, BufferedPacketPtr &toadd,
bool reliable)
{
FATAL_ERROR("unimplemented in abstract class");
}
virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
virtual float getStat(rtt_stat_type type) const {
switch (type) {
case MIN_RTT:
return m_rtt.min_rtt;
case MAX_RTT:
return m_rtt.max_rtt;
case AVG_RTT:
return m_rtt.avg_rtt;
case MIN_JITTER:
return m_rtt.jitter_min;
case MAX_JITTER:
return m_rtt.jitter_max;
case AVG_JITTER:
return m_rtt.jitter_avg;
}
return -1;
}
protected:
Peer(session_t id, const Address &address, Connection *connection) :
IPeer(id),
m_connection(connection),
address(address),
m_last_timeout_check(porting::getTimeMs())
{
}
virtual void reportRTT(float rtt) {};
void RTTStatistics(float rtt,
const std::string &profiler_id = "",
unsigned int num_samples = 1000);
bool IncUseCount();
void DecUseCount();
mutable std::mutex m_exclusive_access_mutex;
bool m_pending_deletion = false;
Connection *m_connection;
// Address of the peer
Address address;
// Ping timer
float m_ping_timer = 0.0f;
private:
struct rttstats {
float jitter_min = FLT_MAX;
float jitter_max = 0.0f;
float jitter_avg = -1.0f;
float min_rtt = FLT_MAX;
float max_rtt = 0.0f;
float avg_rtt = -1.0f;
};
rttstats m_rtt;
float m_last_rtt = -1.0f;
/*
Until the peer has communicated with us using their assigned peer id
the connection is considered half-open.
During this time we inhibit re-sending any reliables or pings. This
is to avoid spending too many resources on a potential DoS attack
and to make sure Minetest servers are not useful for UDP amplificiation.
*/
bool m_half_open = true;
// current usage count
unsigned int m_usage = 0;
// Seconds from last receive
float m_timeout_counter = 0.0f;
u64 m_last_timeout_check;
};
class UDPPeer;
class Connection final : public IConnection
{
public:
friend class ConnectionSendThread;
friend class ConnectionReceiveThread;
Connection(u32 max_packet_size, float timeout, bool ipv6,
PeerHandler *peerhandler);
~Connection();
/* Interface */
ConnectionEventPtr waitEvent(u32 timeout_ms);
void putCommand(ConnectionCommandPtr c);
void Serve(Address bind_addr);
void Connect(Address address);
bool Connected();
void Disconnect();
bool ReceiveTimeoutMs(NetworkPacket *pkt, u32 timeout_ms);
void Send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
session_t GetPeerID() const { return m_peer_id; }
Address GetPeerAddress(session_t peer_id);
float getPeerStat(session_t peer_id, rtt_stat_type type);
float getLocalStat(rate_stat_type type);
u32 GetProtocolID() const { return m_protocol_id; };
const std::string getDesc();
void DisconnectPeer(session_t peer_id);
protected:
PeerHelper getPeerNoEx(session_t peer_id);
session_t lookupPeer(const Address& sender);
session_t createPeer(const Address& sender, int fd);
UDPPeer* createServerPeer(const Address& sender);
bool deletePeer(session_t peer_id, bool timeout);
void SetPeerID(session_t id) { m_peer_id = id; }
void doResendOne(session_t peer_id);
void sendAck(session_t peer_id, u8 channelnum, u16 seqnum);
std::vector<session_t> getPeerIDs()
{
MutexAutoLock peerlock(m_peers_mutex);
return m_peer_ids;
}
u32 getActiveCount();
UDPSocket m_udpSocket;
// Command queue: user -> SendThread
MutexedQueue<ConnectionCommandPtr> m_command_queue;
void putEvent(ConnectionEventPtr e);
void TriggerSend();
bool ConnectedToServer()
{
return getPeerNoEx(PEER_ID_SERVER) != nullptr;
}
private:
// Event queue: ReceiveThread -> user
MutexedQueue<ConnectionEventPtr> m_event_queue;
session_t m_peer_id = 0;
u32 m_protocol_id;
std::map<session_t, Peer *> m_peers;
std::vector<session_t> m_peer_ids;
std::mutex m_peers_mutex;
std::unique_ptr<ConnectionSendThread> m_sendThread;
std::unique_ptr<ConnectionReceiveThread> m_receiveThread;
mutable std::mutex m_info_mutex;
// Backwards compatibility
PeerHandler *m_bc_peerhandler;
bool m_shutting_down = false;
};
} // namespace

View file

@ -19,11 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
/********************************************/
/* may only be included from in src/network */
/********************************************/
#include "network/mtp/impl.h"
#include "connection.h"
// Constant that differentiates the protocol from random data and other protocols
#define PROTOCOL_ID 0x4f457403
#define MAX_UDP_PEERS 65535
@ -161,6 +160,32 @@ inline float CALC_DTIME(u64 lasttime, u64 curtime)
return MYMAX(MYMIN(value, 0.1f), 0.0f);
}
/* Exceptions */
class NotFoundException : public BaseException
{
public:
NotFoundException(const char *s) : BaseException(s) {}
};
class ProcessedSilentlyException : public BaseException
{
public:
ProcessedSilentlyException(const char *s) : BaseException(s) {}
};
class ProcessedQueued : public BaseException
{
public:
ProcessedQueued(const char *s) : BaseException(s) {}
};
class IncomingDataCorruption : public BaseException
{
public:
IncomingDataCorruption(const char *s) : BaseException(s) {}
};
/*
Struct for all kinds of packets. Includes following data:
@ -329,15 +354,24 @@ private:
static ConnectionCommandPtr create(ConnectionCommandType type);
};
/* maximum window size to use, 0xFFFF is theoretical maximum. don't think about
/*
* Window sizes to use, in packets (not bytes!).
* 0xFFFF is theoretical maximum. don't think about
* touching it, the less you're away from it the more likely data corruption
* will occur
*
* Note: window sizes directly translate to maximum possible throughput, e.g.
* (2048 * 512 bytes) / 33ms = 15 MiB/s
*/
// Due to backwards compatibility we have different window sizes for what we'll
// accept from peers vs. what we use for sending.
#define MAX_RELIABLE_WINDOW_SIZE 0x8000
#define MAX_RELIABLE_WINDOW_SIZE_SEND 2048
/* starting value for window size */
#define START_RELIABLE_WINDOW_SIZE 0x400
#define START_RELIABLE_WINDOW_SIZE 64
/* minimum value for window size */
#define MIN_RELIABLE_WINDOW_SIZE 0x40
#define MIN_RELIABLE_WINDOW_SIZE 32
class Channel
{
@ -405,7 +439,7 @@ public:
void setWindowSize(long size)
{
m_window_size = (u16)rangelim(size, MIN_RELIABLE_WINDOW_SIZE, MAX_RELIABLE_WINDOW_SIZE);
m_window_size = (u16)rangelim(size, MIN_RELIABLE_WINDOW_SIZE, MAX_RELIABLE_WINDOW_SIZE_SEND);
}
private:

View file

@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "connectionthreads.h"
#include "network/mtp/threads.h"
#include "log.h"
#include "profiler.h"
#include "settings.h"
@ -35,7 +35,6 @@ namespace con
#define PROFILE(a)
#undef DEBUG_CONNECTION_KBPS
#else
/* this mutex is used to achieve log message consistency */
#define PROFILE(a) a
//#define DEBUG_CONNECTION_KBPS
#undef DEBUG_CONNECTION_KBPS
@ -59,14 +58,24 @@ static inline u8 readChannel(const u8 *packetdata)
/* Connection Threads */
/******************************************************************************/
#define MPPI_SETTING "max_packets_per_iteration"
ConnectionSendThread::ConnectionSendThread(unsigned int max_packet_size,
float timeout) :
Thread("ConnectionSend"),
m_max_packet_size(max_packet_size),
m_timeout(timeout),
m_max_data_packets_per_iteration(g_settings->getU16("max_packets_per_iteration"))
m_max_data_packets_per_iteration(g_settings->getU16(MPPI_SETTING))
{
SANITY_CHECK(m_max_data_packets_per_iteration > 1);
auto &mppi = m_max_data_packets_per_iteration;
mppi = MYMAX(mppi, 1);
const auto mppi_default = Settings::getLayer(SL_DEFAULTS)->getU16(MPPI_SETTING);
if (mppi < mppi_default) {
warningstream << "You are running the network code with a non-default "
"configuration (" MPPI_SETTING "=" << mppi << "). "
"This is not recommended in production." << std::endl;
}
}
void *ConnectionSendThread::run()
@ -211,7 +220,8 @@ void ConnectionSendThread::runTimeouts(float dtime, u32 peer_packet_quota)
}
float resend_timeout = udpPeer->getResendTimeout();
for (Channel &channel : udpPeer->channels) {
for (int ch = 0; ch < CHANNEL_COUNT; ch++) {
auto &channel = udpPeer->channels[ch];
// Remove timed out incomplete unreliable split packets
channel.incoming_splits.removeUnreliableTimedOuts(dtime, peer_timeout);
@ -232,8 +242,8 @@ void ConnectionSendThread::runTimeouts(float dtime, u32 peer_packet_quota)
if (!timed_outs.empty()) {
dout_con << m_connection->getDesc() <<
"Skipping re-send of " << timed_outs.size() <<
" timed-out reliables to peer_id " << udpPeer->id
<< " (half-open)." << std::endl;
" timed-out reliables to peer_id=" << udpPeer->id
<< " channel=" << ch << " (half-open)." << std::endl;
}
continue;
}
@ -246,7 +256,14 @@ void ConnectionSendThread::runTimeouts(float dtime, u32 peer_packet_quota)
for (const auto &k : timed_outs)
resendReliable(channel, k.get(), resend_timeout);
auto ws_old = channel.getWindowSize();
channel.UpdateTimers(dtime);
auto ws_new = channel.getWindowSize();
if (ws_old != ws_new) {
dout_con << m_connection->getDesc() <<
"Window size adjusted to " << ws_new << " for peer_id="
<< udpPeer->id << " channel=" << ch << std::endl;
}
}
/* send ping if necessary */
@ -299,12 +316,12 @@ void ConnectionSendThread::rawSend(const BufferedPacket *p)
assert(p);
try {
m_connection->m_udpSocket.Send(p->address, p->data, p->size());
LOG(dout_con << m_connection->getDesc()
<< " rawSend: " << p->size()
<< " bytes sent" << std::endl);
//LOG(dout_con << m_connection->getDesc()
// << " rawSend: " << p->size()
// << " bytes sent" << std::endl);
} catch (SendFailedException &e) {
LOG(derr_con << m_connection->getDesc()
<< "Connection::rawSend(): SendFailedException: "
<< "SendFailedException: " << e.what() << " to "
<< p->address.serializeString() << std::endl);
}
}
@ -317,6 +334,7 @@ void ConnectionSendThread::sendAsPacketReliable(BufferedPacketPtr &p, Channel *c
channel->outgoing_reliables_sent.insert(p,
(channel->readOutgoingSequenceNumber() - MAX_RELIABLE_WINDOW_SIZE)
% (MAX_RELIABLE_WINDOW_SIZE + 1));
// wtf is this calculation?? ^
}
catch (AlreadyExistsException &e) {
LOG(derr_con << m_connection->getDesc()
@ -675,9 +693,9 @@ void ConnectionSendThread::sendPackets(float dtime, u32 peer_packet_quota)
PROFILE(ScopeProfiler
peerprofiler(g_profiler, peerIdentifier.str(), SPT_AVG));
LOG(dout_con << m_connection->getDesc()
<< " Handle per peer queues: peer_id=" << peerId
<< " packet quota: " << peer->m_increment_packets_remaining << std::endl);
//LOG(dout_con << m_connection->getDesc()
// << " Handle per peer queues: peer_id=" << peerId
// << " packet quota: " << peer->m_increment_packets_remaining << std::endl);
// first send queued reliable packets for all peers (if possible)
for (unsigned int i = 0; i < CHANNEL_COUNT; i++) {
@ -769,7 +787,7 @@ void ConnectionSendThread::sendPackets(float dtime, u32 peer_packet_quota)
}
}
if (peer_packet_quota > 0) {
if (peer_packet_quota > 0 && !stopRequested()) {
for (session_t peerId : peerIds) {
PeerHelper peer = m_connection->getPeerNoEx(peerId);
if (!peer)
@ -1180,7 +1198,7 @@ SharedBuffer<u8> ConnectionReceiveThread::handlePacketType_Control(Channel *chan
// an overflow is quite unlikely but as it'd result in major
// rtt miscalculation we handle it here
if (current_time > p->absolute_send_time) {
float rtt = (current_time - p->absolute_send_time) / 1000.0;
float rtt = (current_time - p->absolute_send_time) / 1000.0f;
// Let peer calculate stuff according to it
// (avg_rtt and resend_timeout)
@ -1325,12 +1343,6 @@ SharedBuffer<u8> ConnectionReceiveThread::handlePacketType_Reliable(Channel *cha
<< ", seqnum: " << seqnum << std::endl;)
m_connection->sendAck(peer->id, channelnum, seqnum);
// we already have this packet so this one was on wire at least
// the current timeout
// we don't know how long this packet was on wire don't do silly guessing
// dynamic_cast<UDPPeer*>(&peer)->
// reportRTT(dynamic_cast<UDPPeer*>(&peer)->getResendTimeout());
throw ProcessedSilentlyException("Retransmitting ack for old packet");
}
}

View file

@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cassert>
#include "threading/thread.h"
#include "connection_internal.h"
#include "network/mtp/internal.h"
namespace con
{

View file

@ -26,11 +26,6 @@ namespace con
/*
Exceptions
*/
class NotFoundException : public BaseException
{
public:
NotFoundException(const char *s) : BaseException(s) {}
};
class PeerNotFoundException : public BaseException
{
@ -56,29 +51,6 @@ public:
InvalidIncomingDataException(const char *s) : BaseException(s) {}
};
class NoIncomingDataException : public BaseException
{
public:
NoIncomingDataException(const char *s) : BaseException(s) {}
};
class ProcessedSilentlyException : public BaseException
{
public:
ProcessedSilentlyException(const char *s) : BaseException(s) {}
};
class ProcessedQueued : public BaseException
{
public:
ProcessedQueued(const char *s) : BaseException(s) {}
};
class IncomingDataCorruption : public BaseException
{
public:
IncomingDataCorruption(const char *s) : BaseException(s) {}
};
}
class SocketException : public BaseException

View file

@ -224,10 +224,26 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Add TOCLIENT_MOVE_PLAYER_REL
Move default minimap from client-side C++ to server-side builtin Lua
[scheduled bump for 5.9.0]
PROTOCOL VERSION 45:
Minimap HUD element supports negative size values as percentages
[bump for 5.9.1]
PROTOCOL VERSION 46:
Move default hotbar from client-side C++ to server-side builtin Lua
Add shadow tint to Lighting packets
Add shadow color to CloudParam packets
Move death screen to server and make it a regular formspec
The server no longer triggers the hardcoded client-side death
formspec, but the client still supports it for compatibility with
old servers.
Rename TOCLIENT_DEATHSCREEN to TOCLIENT_DEATHSCREEN_LEGACY
Rename TOSERVER_RESPAWN to TOSERVER_RESPAWN_LEGACY
[scheduled bump for 5.10.0]
PROTOCOL VERSION 47:
Add artificial light color packet
*/
#define LATEST_PROTOCOL_VERSION 44
#define LATEST_PROTOCOL_VERSION 46
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
// Server's supported network protocol range
@ -238,12 +254,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CLIENT_PROTOCOL_VERSION_MIN 37
#define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
// Constant that differentiates the protocol from random data and other protocols
#define PROTOCOL_ID 0x4f457403
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
// base64-encoded SHA-1 (27+\0).
// See also formspec [Version History] in doc/lua_api.md
#define FORMSPEC_API_VERSION 7
@ -258,10 +268,10 @@ enum ToClientCommand : u16
Sent after TOSERVER_INIT.
u8 deployed serialization version
u16 deployed network compression mode
u16 unused (network compression, never implemeneted)
u16 deployed protocol version
u32 supported auth methods
std::string username that should be used for legacy hash (for proper casing)
std::string unused (used to be username)
*/
TOCLIENT_AUTH_ACCEPT = 0x03,
/*
@ -389,10 +399,10 @@ enum ToClientCommand : u16
f32 transition_time
*/
TOCLIENT_DEATHSCREEN = 0x37,
TOCLIENT_DEATHSCREEN_LEGACY = 0x37,
/*
u8 bool set camera point target
v3f1000 camera point target (to point the death cause or whatever)
u8 bool unused
v3f1000 unused
*/
TOCLIENT_MEDIA = 0x38,
@ -503,22 +513,50 @@ enum ToClientCommand : u16
TOCLIENT_SPAWN_PARTICLE = 0x46,
/*
-- struct range<T> { T min, T max, f32 bias };
using range<T> = RangedParameter<T> {
T min, max
f32 bias
}
using tween<T> = TweenedParameter<T> {
u8 style
u16 reps
f32 beginning
T start, end
}
v3f pos
v3f velocity
v3f acceleration
f32 expirationtime
f32 size
u8 bool collisiondetection
u32 len
u8[len] texture
u8 bool vertical
u8 collision_removal
u8 bool collision_removal
TileAnimation animation
u8 glow
u8 object_collision
u8 bool object_collision
u16 node_param0
u8 node_param2
u8 node_tile
v3f drag
range<v3f> bounce
range<v3f> jitter
range<f32> bounce
texture {
u8 flags (ParticleTextureFlags)
-- bit 0: animated
-- next bits: blend mode (BlendMode)
tween<f32> alpha
tween<v2f> scale
}
*/
TOCLIENT_ADD_PARTICLESPAWNER = 0x47,
@ -537,7 +575,7 @@ enum ToClientCommand : u16
u16 amount
f32 spawntime
if PROTOCOL_VERSION >= 42 {
tween<T> pos, vel, acc, exptime, size
tween<range<T>> pos, vel, acc, exptime, size
} else {
v3f minpos
v3f maxpos
@ -551,14 +589,23 @@ enum ToClientCommand : u16
f32 maxsize
}
u8 bool collisiondetection
u32 len
u8[len] texture
u32 spawner_id
u8 bool vertical
u8 collision_removal
u32 id
u8 bool collision_removal
u32 attached_id
TileAnimation animation
u8 glow
u8 object_collision
u8 bool object_collision
u16 node_param0
u8 node_param2
u8 node_tile
if PROTOCOL_VERSION < 42 {
f32 pos_start_bias
@ -573,6 +620,19 @@ enum ToClientCommand : u16
-- f32 pos_end_bias
range<v3f> vel_end
range<v3f> acc_end
range<f32> exptime_end
range<f32> size_end
}
texture {
u8 flags (ParticleTextureFlags)
-- bit 0: animated
-- next bits: blend mode (BlendMode)
tween<f32> alpha
tween<v2f> scale
if (flags.animated)
TileAnimation animation
}
tween<range<v3f>> drag
@ -598,24 +658,26 @@ enum ToClientCommand : u16
u8 spawner_flags
bit 1: attractor_kill (particles dies on contact)
if attraction_mode > point {
tween<v3f> attractor_angle
u16 attractor_origin_attachment_object_id
tween<v3f> attractor_direction
u16 attractor_direction_attachment_object_id
}
}
tween<range<v3f>> radius
tween<range<v3f>> drag
u16 texpool_sz
texpool_sz.times {
u8 flags
u16 texpool_size
texpool_size.times {
u8 flags (ParticleTextureFlags)
-- bit 0: animated
-- other bits free & ignored as of proto v40
-- next bits: blend mode (BlendMode)
tween<f32> alpha
tween<v2f> scale
if flags.animated {
u32 len
u8[len] texture
if (flags.animated)
TileAnimation animation
}
}
*/
@ -860,7 +922,7 @@ enum ToServerCommand : u16
Sent first after connected.
u8 serialization version (=SER_FMT_VER_HIGHEST_READ)
u16 supported network compression modes
u16 unused (supported network compression modes, never implemeneted)
u16 minimum supported network protocol version
u16 maximum supported network protocol version
std::string player name
@ -948,10 +1010,7 @@ enum ToServerCommand : u16
[2] u16 item
*/
TOSERVER_RESPAWN = 0x38,
/*
u16 TOSERVER_RESPAWN
*/
TOSERVER_RESPAWN_LEGACY = 0x38,
TOSERVER_INTERACT = 0x39,
/*
@ -1095,26 +1154,6 @@ enum AccessDeniedCode : u8 {
SERVER_ACCESSDENIED_MAX,
};
enum NetProtoCompressionMode {
NETPROTO_COMPRESSION_NONE = 0,
};
constexpr const char *accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
"Invalid password",
"Your client sent something the server didn't expect. Try reconnecting or updating your client.",
"The server is running in simple singleplayer mode. You cannot connect.",
"Your client's version is not supported.\nPlease contact the server administrator.",
"Player name contains disallowed characters",
"Player name not allowed",
"Too many users",
"Empty passwords are disallowed. Set a password and try again.",
"Another client is connected with this name. If your client closed unexpectedly, try again in a minute.",
"Internal server error",
"",
"Server shutting down",
"The server has experienced an internal error. You will now be disconnected."
};
enum PlayerListModifer : u8
{
PLAYER_LIST_INIT,
@ -1145,4 +1184,4 @@ enum InteractAction : u8
INTERACT_PLACE, // 3: place block or item (to abovesurface)
INTERACT_USE, // 4: use item
INTERACT_ACTIVATE // 5: rightclick air ("activate")
};
};

View file

@ -19,59 +19,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "networkprotocol.h"
namespace con
{
typedef enum
{
MIN_RTT,
MAX_RTT,
AVG_RTT,
MIN_JITTER,
MAX_JITTER,
AVG_JITTER
} rtt_stat_type;
class Peer;
class IPeer;
class PeerHandler
{
public:
PeerHandler() = default;
virtual ~PeerHandler() = default;
// Note: all functions are called from within a Receive() call on the same thread.
/*
This is called after the Peer has been inserted into the
Connection's peer container.
*/
virtual void peerAdded(Peer *peer) = 0;
virtual void peerAdded(IPeer *peer) = 0;
/*
This is called before the Peer has been removed from the
Connection's peer container.
*/
virtual void deletingPeer(Peer *peer, bool timeout) = 0;
virtual void deletingPeer(IPeer *peer, bool timeout) = 0;
};
enum PeerChangeType : u8
{
PEER_ADDED,
PEER_REMOVED
};
struct PeerChange
{
PeerChange(PeerChangeType t, session_t _peer_id, bool _timeout) :
type(t), peer_id(_peer_id), timeout(_timeout)
{
}
PeerChange() = delete;
PeerChangeType type;
session_t peer_id;
bool timeout;
};
}

View file

@ -82,7 +82,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
{ "TOSERVER_DAMAGE", TOSERVER_STATE_INGAME, &Server::handleCommand_Damage }, // 0x35
null_command_handler, // 0x36
{ "TOSERVER_PLAYERITEM", TOSERVER_STATE_INGAME, &Server::handleCommand_PlayerItem }, // 0x37
{ "TOSERVER_RESPAWN", TOSERVER_STATE_INGAME, &Server::handleCommand_Respawn }, // 0x38
null_command_handler, // 0x38
{ "TOSERVER_INTERACT", TOSERVER_STATE_INGAME, &Server::handleCommand_Interact }, // 0x39
{ "TOSERVER_REMOVED_SOUNDS", TOSERVER_STATE_INGAME, &Server::handleCommand_RemovedSounds }, // 0x3a
{ "TOSERVER_NODEMETA_FIELDS", TOSERVER_STATE_INGAME, &Server::handleCommand_NodeMetaFields }, // 0x3b
@ -181,7 +181,7 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_MOVE_PLAYER", 0, true }, // 0x34
null_command_factory, // 0x35
{ "TOCLIENT_FOV", 0, true }, // 0x36
{ "TOCLIENT_DEATHSCREEN", 0, true }, // 0x37
null_command_factory, // 0x37
{ "TOCLIENT_MEDIA", 2, true }, // 0x38
null_command_factory, // 0x39
{ "TOCLIENT_NODEDEF", 0, true }, // 0x3A

View file

@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include "server.h"
#include "networkprotocol.h"
class NetworkPacket;
// Note: don't forward-declare Server here (#14324)

View file

@ -101,12 +101,12 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
// First byte after command is maximum supported
// serialization version
u8 client_max;
u16 supp_compr_modes;
u16 unused;
u16 min_net_proto_version = 0;
u16 max_net_proto_version;
std::string playerName;
*pkt >> client_max >> supp_compr_modes >> min_net_proto_version
*pkt >> client_max >> unused >> min_net_proto_version
>> max_net_proto_version >> playerName;
u8 our_max = SER_FMT_VER_HIGHEST_READ;
@ -190,9 +190,6 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
}
m_clients.setPlayerName(peer_id, playername);
//TODO (later) case insensitivity
std::string legacyPlayerNameCasing = playerName;
if (!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0) {
actionstream << "Server: Player with the name \"singleplayer\" tried "
@ -279,17 +276,14 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
verbosestream << "Sending TOCLIENT_HELLO with auth method field: "
<< auth_mechs << std::endl;
NetworkPacket resp_pkt(TOCLIENT_HELLO,
1 + 4 + legacyPlayerNameCasing.size(), peer_id);
NetworkPacket resp_pkt(TOCLIENT_HELLO, 0, peer_id);
u16 depl_compress_mode = NETPROTO_COMPRESSION_NONE;
resp_pkt << depl_serial_v << depl_compress_mode << net_proto_version
<< auth_mechs << legacyPlayerNameCasing;
resp_pkt << depl_serial_v << u16(0) << net_proto_version
<< auth_mechs << std::string_view();
Send(&resp_pkt);
client->allowed_auth_mechs = auth_mechs;
client->setDeployedCompressionMode(depl_compress_mode);
m_clients.event(peer_id, CSE_Hello);
}
@ -615,7 +609,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
// If something goes wrong, this player is to blame
RollbackScopeActor rollback_scope(m_rollback,
std::string("player:")+player->getName());
"player:" + player->getName());
/*
Note: Always set inventory not sent, to repair cases
@ -852,11 +846,11 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
*pkt >> item;
if (item >= player->getHotbarItemcount()) {
if (item >= player->getMaxHotbarItemcount()) {
actionstream << "Player: " << player->getName()
<< " tried to access item=" << item
<< " out of hotbar_itemcount="
<< player->getHotbarItemcount()
<< player->getMaxHotbarItemcount()
<< "; ignoring." << std::endl;
return;
}
@ -864,33 +858,6 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
playersao->getPlayer()->setWieldIndex(item);
}
void Server::handleCommand_Respawn(NetworkPacket* pkt)
{
session_t peer_id = pkt->getPeerId();
RemotePlayer *player = m_env->getPlayer(peer_id);
if (player == NULL) {
errorstream <<
"Server::ProcessData(): Canceling: No player for peer_id=" <<
peer_id << " disconnecting peer!" << std::endl;
DisconnectPeer(peer_id);
return;
}
PlayerSAO *playersao = player->getPlayerSAO();
assert(playersao);
if (!playersao->isDead())
return;
RespawnPlayer(peer_id);
actionstream << player->getName() << " respawns at "
<< (playersao->getBasePosition() / BS) << std::endl;
// ActiveObject is added to environment in AsyncRunStep after
// the previous addition has been successfully removed
}
bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string &what)
{
ItemStack selected_item, hand_item;
@ -983,11 +950,11 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
// Update wielded item
if (item_i >= player->getHotbarItemcount()) {
if (item_i >= player->getMaxHotbarItemcount()) {
actionstream << "Player: " << player->getName()
<< " tried to access item=" << item_i
<< " out of hotbar_itemcount="
<< player->getHotbarItemcount()
<< player->getMaxHotbarItemcount()
<< "; ignoring." << std::endl;
return;
}
@ -1069,7 +1036,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
If something goes wrong, this player is to blame
*/
RollbackScopeActor rollback_scope(m_rollback,
std::string("player:")+player->getName());
"player:" + player->getName());
switch (action) {
// Start digging or punch object
@ -1351,15 +1318,22 @@ static bool pkt_read_formspec_fields(NetworkPacket *pkt, StringMap &fields)
u16 field_count;
*pkt >> field_count;
u64 length = 0;
size_t length = 0;
for (u16 k = 0; k < field_count; k++) {
std::string fieldname;
std::string fieldname, fieldvalue;
*pkt >> fieldname;
fields[fieldname] = pkt->readLongString();
fieldvalue = pkt->readLongString();
length += fieldname.size();
length += fields[fieldname].size();
fieldname = sanitize_untrusted(fieldname, false);
// We'd love to strip escapes here but some formspec elements reflect data
// from the server (e.g. dropdown), which can contain translations.
fieldvalue = sanitize_untrusted(fieldvalue);
length += fieldname.size() + fieldvalue.size();
fields[std::move(fieldname)] = std::move(fieldvalue);
}
// 640K ought to be enough for anyone
return length < 640 * 1024;
}
@ -1400,7 +1374,7 @@ void Server::handleCommand_NodeMetaFields(NetworkPacket* pkt)
// If something goes wrong, this player is to blame
RollbackScopeActor rollback_scope(m_rollback,
std::string("player:")+player->getName());
"player:" + player->getName());
// Check the target node for rollback data; leave others unnoticed
RollbackNode rn_old(&m_env->getMap(), p, this);

View file

@ -50,9 +50,6 @@ typedef int socklen_t;
#define SOCKET_ERR_STR(e) strerror(e)
#endif
// Set to true to enable verbose debug output
bool socket_enable_debug_output = false; // yuck
static bool g_sockets_initialized = false;
// Initialize sockets
@ -104,12 +101,6 @@ bool UDPSocket::init(bool ipv6, bool noExceptions)
m_addr_family = ipv6 ? AF_INET6 : AF_INET;
m_handle = socket(m_addr_family, SOCK_DGRAM, IPPROTO_UDP);
if (socket_enable_debug_output) {
tracestream << "UDPSocket(" << (int)m_handle
<< ")::UDPSocket(): ipv6 = " << (ipv6 ? "true" : "false")
<< std::endl;
}
if (m_handle < 0) {
if (noExceptions) {
return false;
@ -135,11 +126,6 @@ bool UDPSocket::init(bool ipv6, bool noExceptions)
UDPSocket::~UDPSocket()
{
if (socket_enable_debug_output) {
tracestream << "UDPSocket( " << (int)m_handle << ")::~UDPSocket()"
<< std::endl;
}
if (m_handle >= 0) {
#ifdef _WIN32
closesocket(m_handle);
@ -151,12 +137,6 @@ UDPSocket::~UDPSocket()
void UDPSocket::Bind(Address addr)
{
if (socket_enable_debug_output) {
tracestream << "UDPSocket(" << (int)m_handle
<< ")::Bind(): " << addr.serializeString() << ":"
<< addr.getPort() << std::endl;
}
if (addr.getFamily() != m_addr_family) {
const char *errmsg =
"Socket and bind address families do not match";
@ -202,30 +182,6 @@ void UDPSocket::Send(const Address &destination, const void *data, int size)
if (INTERNET_SIMULATOR)
dumping_packet = myrand() % INTERNET_SIMULATOR_PACKET_LOSS == 0;
if (socket_enable_debug_output) {
// Print packet destination and size
tracestream << (int)m_handle << " -> ";
destination.print(tracestream);
tracestream << ", size=" << size;
// Print packet contents
tracestream << ", data=";
for (int i = 0; i < size && i < 20; i++) {
if (i % 2 == 0)
tracestream << " ";
unsigned int a = ((const unsigned char *)data)[i];
tracestream << std::hex << std::setw(2) << std::setfill('0') << a;
}
if (size > 20)
tracestream << "...";
if (dumping_packet)
tracestream << " (DUMPED BY INTERNET_SIMULATOR)";
tracestream << std::endl;
}
if (dumping_packet) {
// Lol let's forget it
tracestream << "UDPSocket::Send(): INTERNET_SIMULATOR: dumping packet."
@ -302,26 +258,6 @@ int UDPSocket::Receive(Address &sender, void *data, int size)
sender = Address(address_ip, address_port);
}
if (socket_enable_debug_output) {
// Print packet sender and size
tracestream << (int)m_handle << " <- ";
sender.print(tracestream);
tracestream << ", size=" << received;
// Print packet contents
tracestream << ", data=";
for (int i = 0; i < received && i < 20; i++) {
if (i % 2 == 0)
tracestream << " ";
unsigned int a = ((const unsigned char *)data)[i];
tracestream << std::hex << std::setw(2) << std::setfill('0') << a;
}
if (received > 20)
tracestream << "...";
tracestream << std::endl;
}
return received;
}

View file

@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include "networkexceptions.h"
extern bool socket_enable_debug_output;
void sockets_init();
void sockets_cleanup();