connection.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include "irrlichttypes.h"
  18. #include "peerhandler.h"
  19. #include "socket.h"
  20. #include "constants.h"
  21. #include "util/pointer.h"
  22. #include "util/container.h"
  23. #include "util/numeric.h"
  24. #include "porting.h"
  25. #include "networkprotocol.h"
  26. #include <iostream>
  27. #include <vector>
  28. #include <map>
  29. class NetworkPacket;
  30. namespace con
  31. {
  32. class ConnectionReceiveThread;
  33. class ConnectionSendThread;
  34. enum rate_stat_type {
  35. CUR_DL_RATE,
  36. AVG_DL_RATE,
  37. CUR_INC_RATE,
  38. AVG_INC_RATE,
  39. CUR_LOSS_RATE,
  40. AVG_LOSS_RATE,
  41. };
  42. class Peer;
  43. // FIXME: Peer refcounting should generally be replaced by std::shared_ptr
  44. class PeerHelper
  45. {
  46. public:
  47. PeerHelper() = default;
  48. inline PeerHelper(Peer *peer) { *this = peer; }
  49. ~PeerHelper();
  50. PeerHelper& operator=(Peer *peer);
  51. inline Peer* operator->() const { return m_peer; }
  52. inline Peer* operator&() const { return m_peer; }
  53. inline bool operator!() { return !m_peer; }
  54. inline bool operator!=(std::nullptr_t) { return !!m_peer; }
  55. private:
  56. Peer *m_peer = nullptr;
  57. };
  58. /*
  59. Connection
  60. */
  61. enum ConnectionEventType {
  62. CONNEVENT_NONE,
  63. CONNEVENT_DATA_RECEIVED,
  64. CONNEVENT_PEER_ADDED,
  65. CONNEVENT_PEER_REMOVED,
  66. CONNEVENT_BIND_FAILED,
  67. };
  68. struct ConnectionEvent;
  69. typedef std::shared_ptr<ConnectionEvent> ConnectionEventPtr;
  70. // This is very similar to ConnectionCommand
  71. struct ConnectionEvent
  72. {
  73. const ConnectionEventType type;
  74. session_t peer_id = 0;
  75. Buffer<u8> data;
  76. bool timeout = false;
  77. Address address;
  78. // We don't want to copy "data"
  79. DISABLE_CLASS_COPY(ConnectionEvent);
  80. static ConnectionEventPtr create(ConnectionEventType type);
  81. static ConnectionEventPtr dataReceived(session_t peer_id, const Buffer<u8> &data);
  82. static ConnectionEventPtr peerAdded(session_t peer_id, Address address);
  83. static ConnectionEventPtr peerRemoved(session_t peer_id, bool is_timeout, Address address);
  84. static ConnectionEventPtr bindFailed();
  85. const char *describe() const;
  86. private:
  87. ConnectionEvent(ConnectionEventType type_) :
  88. type(type_) {}
  89. };
  90. struct ConnectionCommand;
  91. typedef std::shared_ptr<ConnectionCommand> ConnectionCommandPtr;
  92. struct BufferedPacket;
  93. typedef std::shared_ptr<BufferedPacket> BufferedPacketPtr;
  94. class Connection;
  95. class PeerHandler;
  96. class Peer {
  97. public:
  98. friend class PeerHelper;
  99. virtual ~Peer() {
  100. MutexAutoLock usage_lock(m_exclusive_access_mutex);
  101. FATAL_ERROR_IF(m_usage != 0, "Reference counting failure");
  102. }
  103. // Unique id of the peer
  104. const session_t id;
  105. void Drop();
  106. virtual void PutReliableSendCommand(ConnectionCommandPtr &c,
  107. unsigned int max_packet_size) {};
  108. virtual const Address &getAddress() const = 0;
  109. bool isPendingDeletion() const {
  110. MutexAutoLock lock(m_exclusive_access_mutex);
  111. return m_pending_deletion;
  112. }
  113. void ResetTimeout() {
  114. MutexAutoLock lock(m_exclusive_access_mutex);
  115. m_timeout_counter = 0;
  116. }
  117. bool isHalfOpen() const {
  118. MutexAutoLock lock(m_exclusive_access_mutex);
  119. return m_half_open;
  120. }
  121. void SetFullyOpen() {
  122. MutexAutoLock lock(m_exclusive_access_mutex);
  123. m_half_open = false;
  124. }
  125. virtual bool isTimedOut(float timeout, std::string &reason);
  126. unsigned int m_increment_packets_remaining = 0;
  127. virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; };
  128. virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {};
  129. virtual SharedBuffer<u8> addSplitPacket(u8 channel, BufferedPacketPtr &toadd,
  130. bool reliable)
  131. {
  132. FATAL_ERROR("unimplemented in abstract class");
  133. }
  134. virtual bool Ping(float dtime, SharedBuffer<u8>& data) { return false; };
  135. virtual float getStat(rtt_stat_type type) const {
  136. switch (type) {
  137. case MIN_RTT:
  138. return m_rtt.min_rtt;
  139. case MAX_RTT:
  140. return m_rtt.max_rtt;
  141. case AVG_RTT:
  142. return m_rtt.avg_rtt;
  143. case MIN_JITTER:
  144. return m_rtt.jitter_min;
  145. case MAX_JITTER:
  146. return m_rtt.jitter_max;
  147. case AVG_JITTER:
  148. return m_rtt.jitter_avg;
  149. }
  150. return -1;
  151. }
  152. protected:
  153. Peer(session_t id, const Address &address, Connection *connection) :
  154. id(id),
  155. m_connection(connection),
  156. address(address),
  157. m_last_timeout_check(porting::getTimeMs())
  158. {
  159. }
  160. virtual void reportRTT(float rtt) {};
  161. void RTTStatistics(float rtt,
  162. const std::string &profiler_id = "",
  163. unsigned int num_samples = 1000);
  164. bool IncUseCount();
  165. void DecUseCount();
  166. mutable std::mutex m_exclusive_access_mutex;
  167. bool m_pending_deletion = false;
  168. Connection *m_connection;
  169. // Address of the peer
  170. Address address;
  171. // Ping timer
  172. float m_ping_timer = 0.0f;
  173. private:
  174. struct rttstats {
  175. float jitter_min = FLT_MAX;
  176. float jitter_max = 0.0f;
  177. float jitter_avg = -1.0f;
  178. float min_rtt = FLT_MAX;
  179. float max_rtt = 0.0f;
  180. float avg_rtt = -1.0f;
  181. };
  182. rttstats m_rtt;
  183. float m_last_rtt = -1.0f;
  184. /*
  185. Until the peer has communicated with us using their assigned peer id
  186. the connection is considered half-open.
  187. During this time we inhibit re-sending any reliables or pings. This
  188. is to avoid spending too many resources on a potential DoS attack
  189. and to make sure Minetest servers are not useful for UDP amplificiation.
  190. */
  191. bool m_half_open = true;
  192. // current usage count
  193. unsigned int m_usage = 0;
  194. // Seconds from last receive
  195. float m_timeout_counter = 0.0f;
  196. u64 m_last_timeout_check;
  197. };
  198. class UDPPeer;
  199. class Connection
  200. {
  201. public:
  202. friend class ConnectionSendThread;
  203. friend class ConnectionReceiveThread;
  204. Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6,
  205. PeerHandler *peerhandler);
  206. ~Connection();
  207. /* Interface */
  208. ConnectionEventPtr waitEvent(u32 timeout_ms);
  209. void putCommand(ConnectionCommandPtr c);
  210. void SetTimeoutMs(u32 timeout) { m_bc_receive_timeout = timeout; }
  211. void Serve(Address bind_addr);
  212. void Connect(Address address);
  213. bool Connected();
  214. void Disconnect();
  215. bool ReceiveTimeoutMs(NetworkPacket *pkt, u32 timeout_ms);
  216. void Receive(NetworkPacket *pkt);
  217. bool TryReceive(NetworkPacket *pkt);
  218. void Send(session_t peer_id, u8 channelnum, NetworkPacket *pkt, bool reliable);
  219. session_t GetPeerID() const { return m_peer_id; }
  220. Address GetPeerAddress(session_t peer_id);
  221. float getPeerStat(session_t peer_id, rtt_stat_type type);
  222. float getLocalStat(rate_stat_type type);
  223. u32 GetProtocolID() const { return m_protocol_id; };
  224. const std::string getDesc();
  225. void DisconnectPeer(session_t peer_id);
  226. protected:
  227. PeerHelper getPeerNoEx(session_t peer_id);
  228. session_t lookupPeer(const Address& sender);
  229. session_t createPeer(const Address& sender, int fd);
  230. UDPPeer* createServerPeer(const Address& sender);
  231. bool deletePeer(session_t peer_id, bool timeout);
  232. void SetPeerID(session_t id) { m_peer_id = id; }
  233. void doResendOne(session_t peer_id);
  234. void sendAck(session_t peer_id, u8 channelnum, u16 seqnum);
  235. std::vector<session_t> getPeerIDs()
  236. {
  237. MutexAutoLock peerlock(m_peers_mutex);
  238. return m_peer_ids;
  239. }
  240. u32 getActiveCount();
  241. UDPSocket m_udpSocket;
  242. // Command queue: user -> SendThread
  243. MutexedQueue<ConnectionCommandPtr> m_command_queue;
  244. void putEvent(ConnectionEventPtr e);
  245. void TriggerSend();
  246. bool ConnectedToServer()
  247. {
  248. return getPeerNoEx(PEER_ID_SERVER) != nullptr;
  249. }
  250. private:
  251. // Event queue: ReceiveThread -> user
  252. MutexedQueue<ConnectionEventPtr> m_event_queue;
  253. session_t m_peer_id = 0;
  254. u32 m_protocol_id;
  255. std::map<session_t, Peer *> m_peers;
  256. std::vector<session_t> m_peer_ids;
  257. std::mutex m_peers_mutex;
  258. std::unique_ptr<ConnectionSendThread> m_sendThread;
  259. std::unique_ptr<ConnectionReceiveThread> m_receiveThread;
  260. mutable std::mutex m_info_mutex;
  261. // Backwards compatibility
  262. PeerHandler *m_bc_peerhandler;
  263. u32 m_bc_receive_timeout = 0;
  264. bool m_shutting_down = false;
  265. };
  266. } // namespace