mirror of
https://github.com/minetest/minetest.git
synced 2024-12-22 22:22:23 +01:00
Move network protocol implementation behind an interface
This commit is contained in:
parent
c6ef5ab259
commit
7968ab6928
@ -392,8 +392,7 @@ void Client::connect(const Address &address, const std::string &address_name,
|
||||
}
|
||||
|
||||
m_address_name = address_name;
|
||||
m_con.reset(new con::Connection(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
|
||||
address.isIPv6(), this));
|
||||
m_con.reset(con::createMTP(CONNECTION_TIMEOUT, address.isIPv6(), this));
|
||||
|
||||
infostream << "Connecting to server at ";
|
||||
address.print(infostream);
|
||||
@ -866,13 +865,13 @@ bool Client::loadMedia(const std::string &data, const std::string &filename,
|
||||
}
|
||||
|
||||
// Virtual methods from con::PeerHandler
|
||||
void Client::peerAdded(con::Peer *peer)
|
||||
void Client::peerAdded(con::IPeer *peer)
|
||||
{
|
||||
infostream << "Client::peerAdded(): peer->id="
|
||||
<< peer->id << std::endl;
|
||||
}
|
||||
|
||||
void Client::deletingPeer(con::Peer *peer, bool timeout)
|
||||
void Client::deletingPeer(con::IPeer *peer, bool timeout)
|
||||
{
|
||||
infostream << "Client::deletingPeer(): "
|
||||
"Server Peer is getting deleted "
|
||||
|
@ -71,7 +71,7 @@ class Camera;
|
||||
struct PlayerControl;
|
||||
class NetworkPacket;
|
||||
namespace con {
|
||||
class Connection;
|
||||
class IConnection;
|
||||
}
|
||||
using sound_handle_t = int;
|
||||
|
||||
@ -452,8 +452,8 @@ private:
|
||||
void loadMods();
|
||||
|
||||
// Virtual methods from con::PeerHandler
|
||||
void peerAdded(con::Peer *peer) override;
|
||||
void deletingPeer(con::Peer *peer, bool timeout) override;
|
||||
void peerAdded(con::IPeer *peer) override;
|
||||
void deletingPeer(con::IPeer *peer, bool timeout) override;
|
||||
|
||||
void initLocalMapSaving(const Address &address,
|
||||
const std::string &hostname,
|
||||
@ -493,7 +493,7 @@ private:
|
||||
std::unique_ptr<MeshUpdateManager> m_mesh_update_manager;
|
||||
ClientEnvironment m_env;
|
||||
std::unique_ptr<ParticleManager> m_particle_manager;
|
||||
std::unique_ptr<con::Connection> m_con;
|
||||
std::unique_ptr<con::IConnection> m_con;
|
||||
std::string m_address_name;
|
||||
ELoginRegister m_allow_login_or_register = ELoginRegister::Any;
|
||||
Camera *m_camera = nullptr;
|
||||
|
@ -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
|
||||
)
|
||||
|
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,45 @@ 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 SetTimeoutMs(u32 timeout) = 0;
|
||||
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;
|
||||
virtual void Receive(NetworkPacket *pkt) = 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
|
||||
|
1667
src/network/mtp/impl.cpp
Normal file
1667
src/network/mtp/impl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
325
src/network/mtp/impl.h
Normal file
325
src/network/mtp/impl.h
Normal file
@ -0,0 +1,325 @@
|
||||
/*
|
||||
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 : 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 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);
|
||||
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;
|
||||
u32 m_bc_receive_timeout = 0;
|
||||
|
||||
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:
|
@ -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"
|
@ -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
|
||||
{
|
||||
@ -62,23 +57,6 @@ 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
|
||||
|
@ -237,9 +237,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).
|
||||
|
||||
|
@ -24,17 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
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
|
||||
{
|
||||
@ -47,13 +37,13 @@ public:
|
||||
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
|
||||
|
@ -258,11 +258,7 @@ Server::Server(
|
||||
m_simple_singleplayer_mode(simple_singleplayer_mode),
|
||||
m_dedicated(dedicated),
|
||||
m_async_fatal_error(""),
|
||||
m_con(std::make_shared<con::Connection>(PROTOCOL_ID,
|
||||
512,
|
||||
CONNECTION_TIMEOUT,
|
||||
m_bind_addr.isIPv6(),
|
||||
this)),
|
||||
m_con(con::createMTP(CONNECTION_TIMEOUT, m_bind_addr.isIPv6(), this)),
|
||||
m_itemdef(createItemDefManager()),
|
||||
m_nodedef(createNodeDefManager()),
|
||||
m_craftdef(createCraftDefManager()),
|
||||
@ -1258,7 +1254,7 @@ void Server::onMapEditEvent(const MapEditEvent &event)
|
||||
m_unsent_map_edit_queue.push(new MapEditEvent(event));
|
||||
}
|
||||
|
||||
void Server::peerAdded(con::Peer *peer)
|
||||
void Server::peerAdded(con::IPeer *peer)
|
||||
{
|
||||
verbosestream<<"Server::peerAdded(): peer->id="
|
||||
<<peer->id<<std::endl;
|
||||
@ -1266,7 +1262,7 @@ void Server::peerAdded(con::Peer *peer)
|
||||
m_peer_change_queue.push(con::PeerChange(con::PEER_ADDED, peer->id, false));
|
||||
}
|
||||
|
||||
void Server::deletingPeer(con::Peer *peer, bool timeout)
|
||||
void Server::deletingPeer(con::IPeer *peer, bool timeout)
|
||||
{
|
||||
verbosestream<<"Server::deletingPeer(): peer->id="
|
||||
<<peer->id<<", timeout="<<timeout<<std::endl;
|
||||
|
@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "inventorymanager.h"
|
||||
#include "content/subgames.h"
|
||||
#include "network/peerhandler.h"
|
||||
#include "network/address.h"
|
||||
#include "network/connection.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/basic_macros.h"
|
||||
@ -359,8 +359,8 @@ public:
|
||||
void RespawnPlayer(session_t peer_id);
|
||||
|
||||
/* con::PeerHandler implementation. */
|
||||
void peerAdded(con::Peer *peer);
|
||||
void deletingPeer(con::Peer *peer, bool timeout);
|
||||
void peerAdded(con::IPeer *peer);
|
||||
void deletingPeer(con::IPeer *peer, bool timeout);
|
||||
|
||||
void DenySudoAccess(session_t peer_id);
|
||||
void DenyAccess(session_t peer_id, AccessDeniedCode reason,
|
||||
@ -637,7 +637,7 @@ private:
|
||||
ServerEnvironment *m_env = nullptr;
|
||||
|
||||
// server connection
|
||||
std::shared_ptr<con::Connection> m_con;
|
||||
std::shared_ptr<con::IConnection> m_con;
|
||||
|
||||
// Ban checking
|
||||
BanManager *m_banmanager = nullptr;
|
||||
|
@ -648,13 +648,14 @@ void RemoteClient::setLangCode(const std::string &code)
|
||||
m_lang_code = string_sanitize_ascii(code, 12);
|
||||
}
|
||||
|
||||
ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
|
||||
ClientInterface::ClientInterface(const std::shared_ptr<con::IConnection> &con)
|
||||
:
|
||||
m_con(con),
|
||||
m_env(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ClientInterface::~ClientInterface()
|
||||
{
|
||||
/*
|
||||
|
@ -168,7 +168,7 @@ class EmergeManager;
|
||||
|
||||
*/
|
||||
namespace con {
|
||||
class Connection;
|
||||
class IConnection;
|
||||
}
|
||||
|
||||
|
||||
@ -464,7 +464,7 @@ public:
|
||||
|
||||
friend class Server;
|
||||
|
||||
ClientInterface(const std::shared_ptr<con::Connection> &con);
|
||||
ClientInterface(const std::shared_ptr<con::IConnection> &con);
|
||||
~ClientInterface();
|
||||
|
||||
/* run sync step */
|
||||
@ -543,7 +543,7 @@ private:
|
||||
void UpdatePlayerList();
|
||||
|
||||
// Connection
|
||||
std::shared_ptr<con::Connection> m_con;
|
||||
std::shared_ptr<con::IConnection> m_con;
|
||||
std::recursive_mutex m_clients_mutex;
|
||||
// Connected clients (behind the con mutex)
|
||||
RemoteClientMap m_clients;
|
||||
|
@ -23,7 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "porting.h"
|
||||
#include "settings.h"
|
||||
#include "util/serialize.h"
|
||||
#include "network/connection_internal.h"
|
||||
#include "network/peerhandler.h"
|
||||
#include "network/mtp/internal.h"
|
||||
#include "network/networkpacket.h"
|
||||
#include "network/socket.h"
|
||||
|
||||
@ -59,7 +60,7 @@ struct Handler : public con::PeerHandler
|
||||
{
|
||||
Handler(const char *a_name) : name(a_name) {}
|
||||
|
||||
void peerAdded(con::Peer *peer)
|
||||
void peerAdded(con::IPeer *peer)
|
||||
{
|
||||
infostream << "Handler(" << name << ")::peerAdded(): "
|
||||
"id=" << peer->id << std::endl;
|
||||
@ -67,7 +68,7 @@ struct Handler : public con::PeerHandler
|
||||
count++;
|
||||
}
|
||||
|
||||
void deletingPeer(con::Peer *peer, bool timeout)
|
||||
void deletingPeer(con::IPeer *peer, bool timeout)
|
||||
{
|
||||
infostream << "Handler(" << name << ")::deletingPeer(): "
|
||||
"id=" << peer->id << ", timeout=" << timeout << std::endl;
|
||||
@ -165,8 +166,6 @@ void TestConnection::testConnectSendReceive()
|
||||
NOTE: This mostly tests the legacy interface.
|
||||
*/
|
||||
|
||||
u32 proto_id = 0xad26846a;
|
||||
|
||||
Handler hand_server("server");
|
||||
Handler hand_client("client");
|
||||
|
||||
@ -187,11 +186,11 @@ void TestConnection::testConnectSendReceive()
|
||||
}
|
||||
|
||||
infostream << "** Creating server Connection" << std::endl;
|
||||
con::Connection server(proto_id, 512, 5.0, false, &hand_server);
|
||||
con::Connection server(512, 5.0f, false, &hand_server);
|
||||
server.Serve(address);
|
||||
|
||||
infostream << "** Creating client Connection" << std::endl;
|
||||
con::Connection client(proto_id, 512, 5.0, false, &hand_client);
|
||||
con::Connection client(512, 5.0f, false, &hand_client);
|
||||
|
||||
UASSERT(hand_server.count == 0);
|
||||
UASSERT(hand_client.count == 0);
|
||||
|
Loading…
Reference in New Issue
Block a user