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:
commit
71e648a776
647 changed files with 60434 additions and 37195 deletions
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
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
322
src/network/mtp/impl.h
Normal 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
|
|
@ -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:
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
};
|
||||
};
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue