diff options
author | Loic Blot <loic.blot@unix-experience.fr> | 2015-01-16 11:37:49 +0100 |
---|---|---|
committer | Loic Blot <loic.blot@unix-experience.fr> | 2015-02-16 11:00:55 +0100 |
commit | ed04e8e9e407f0dd57fa83a9732b3a3968cb80e0 (patch) | |
tree | 488c3b155e78072c0f65a26b8e34b530d059f56c /src/connection.h | |
parent | efa977518a60c47f3c409449be202298900372e8 (diff) | |
download | minetest-ed04e8e9e407f0dd57fa83a9732b3a3968cb80e0.tar.gz minetest-ed04e8e9e407f0dd57fa83a9732b3a3968cb80e0.tar.bz2 minetest-ed04e8e9e407f0dd57fa83a9732b3a3968cb80e0.zip |
[Patch 2/4] Network rework: packet writing, sending and cleanups
NetworkPacket.cpp:
* Remove some deprecated functions, we must use streaming interface
* m_data converted from u8* to std::vector<u8>
* Add an exporter to forge packet to Connection object
* implement operator << std::wstring. n
* implement operator << std::string
* dynamic resize when write packet content.
* fix string writing and performances.
* create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Reliability
* Transmit channel
* Implement putRawString for some ugly char (_INIT packet), and use it.
* Many packet read and write migrated
* Implement oldForgePacket to interface writing with current connection
* fix U8/char/bool writing
* fix string writing and performances.
* add some missing functions
* Use v3s16 read instead of reading x,y,z separately
* Add irr::video::SColor support into packets
* Add some missing handlers
* Add a template function to increase offset
* Throw a serialization error on packet reading (must be improved)
PacketFactories:
* Create ServerCommandFactory, used by client to get useful informations about packet processing (sending).
* Create ClientCommandFactory, used by server to get useful informations about packet processing (sending).
Client.cpp:
* implement NetworkPacket ::Send interface.
* Move packet handlers to a dedicated file
* Remove Client::Send(SharedBuffer)
Server.cpp:
* implement NetworkPacket ::Send interface.
* Rewrite all packets using NetworkPacket
* Move packet handlers to a dedicated file
* Remove Server::Send(SharedBuffer)
ClientIface.cpp:
* Remove sendToAll(SharedBuffer<u8>)
Connection.hpp rework:
* Remove duplicate include
* Remove duplicate negation
* Remove a useless variable
* Improve code performance by using a m_peers_list instead of scanning m_peers map
* Remove Connection::Send(SharedBuffer)
* Fix useafterfree into NetworkPacket Sending
* Remove unused Connection::sendToAll
Test.cpp:
* Remove dead code
* Update tests to use NetworkPackets
Misc:
* add new wrappers to Send packets in client, using NetworkPacket
* Add NetworkPacket methods for Connection
* coding style fix
* dead code since changes cleanup
* Use v3s16 read instead of reading x,y,z separately in some packets
* Use different files to handle packets received by client and server
* Cleanup: Remove useless includes
ok @Zeno-
Tested by @Zeno- @VanessaE and @nerzhul on running servers
Diffstat (limited to 'src/connection.h')
-rw-r--r-- | src/connection.h | 1098 |
1 files changed, 0 insertions, 1098 deletions
diff --git a/src/connection.h b/src/connection.h deleted file mode 100644 index be1627dfa..000000000 --- a/src/connection.h +++ /dev/null @@ -1,1098 +0,0 @@ -/* -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. -*/ - -#ifndef CONNECTION_HEADER -#define CONNECTION_HEADER - -#include "irrlichttypes_bloated.h" -#include "socket.h" -#include "exceptions.h" -#include "constants.h" -#include "util/pointer.h" -#include "util/container.h" -#include "util/thread.h" -#include "util/numeric.h" -#include <iostream> -#include <fstream> -#include <list> -#include <map> - -namespace con -{ - -/* - Exceptions -*/ -class NotFoundException : public BaseException -{ -public: - NotFoundException(const char *s): - BaseException(s) - {} -}; - -class PeerNotFoundException : public BaseException -{ -public: - PeerNotFoundException(const char *s): - BaseException(s) - {} -}; - -class ConnectionException : public BaseException -{ -public: - ConnectionException(const char *s): - BaseException(s) - {} -}; - -class ConnectionBindFailed : public BaseException -{ -public: - ConnectionBindFailed(const char *s): - BaseException(s) - {} -}; - -class InvalidIncomingDataException : public BaseException -{ -public: - InvalidIncomingDataException(const char *s): - BaseException(s) - {} -}; - -class InvalidOutgoingDataException : public BaseException -{ -public: - InvalidOutgoingDataException(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) - {} -}; - -typedef enum MTProtocols { - MTP_PRIMARY, - MTP_UDP, - MTP_MINETEST_RELIABLE_UDP -} MTProtocols; - -#define SEQNUM_MAX 65535 -inline bool seqnum_higher(u16 totest, u16 base) -{ - if (totest > base) - { - if((totest - base) > (SEQNUM_MAX/2)) - return false; - else - return true; - } - else - { - if((base - totest) > (SEQNUM_MAX/2)) - return true; - else - return false; - } -} - -inline bool seqnum_in_window(u16 seqnum, u16 next,u16 window_size) -{ - u16 window_start = next; - u16 window_end = ( next + window_size ) % (SEQNUM_MAX+1); - - if (window_start < window_end) - { - return ((seqnum >= window_start) && (seqnum < window_end)); - } - else - { - return ((seqnum < window_end) || (seqnum >= window_start)); - } -} - -struct BufferedPacket -{ - BufferedPacket(u8 *a_data, u32 a_size): - data(a_data, a_size), time(0.0), totaltime(0.0), absolute_send_time(-1), - resend_count(0) - {} - BufferedPacket(u32 a_size): - data(a_size), time(0.0), totaltime(0.0), absolute_send_time(-1), - resend_count(0) - {} - SharedBuffer<u8> data; // Data of the packet, including headers - float time; // Seconds from buffering the packet or re-sending - float totaltime; // Seconds from buffering the packet - unsigned int absolute_send_time; - Address address; // Sender or destination - unsigned int resend_count; -}; - -// This adds the base headers to the data and makes a packet out of it -BufferedPacket makePacket(Address &address, u8 *data, u32 datasize, - u32 protocol_id, u16 sender_peer_id, u8 channel); -BufferedPacket makePacket(Address &address, SharedBuffer<u8> &data, - u32 protocol_id, u16 sender_peer_id, u8 channel); - -// Add the TYPE_ORIGINAL header to the data -SharedBuffer<u8> makeOriginalPacket( - SharedBuffer<u8> data); - -// Split data in chunks and add TYPE_SPLIT headers to them -std::list<SharedBuffer<u8> > makeSplitPacket( - SharedBuffer<u8> data, - u32 chunksize_max, - u16 seqnum); - -// Depending on size, make a TYPE_ORIGINAL or TYPE_SPLIT packet -// Increments split_seqnum if a split packet is made -std::list<SharedBuffer<u8> > makeAutoSplitPacket( - SharedBuffer<u8> data, - u32 chunksize_max, - u16 &split_seqnum); - -// Add the TYPE_RELIABLE header to the data -SharedBuffer<u8> makeReliablePacket( - SharedBuffer<u8> data, - u16 seqnum); - -struct IncomingSplitPacket -{ - IncomingSplitPacket() - { - time = 0.0; - reliable = false; - } - // Key is chunk number, value is data without headers - std::map<u16, SharedBuffer<u8> > chunks; - u32 chunk_count; - float time; // Seconds from adding - bool reliable; // If true, isn't deleted on timeout - - bool allReceived() - { - return (chunks.size() == chunk_count); - } -}; - -/* -=== NOTES === - -A packet is sent through a channel to a peer with a basic header: -TODO: Should we have a receiver_peer_id also? - Header (7 bytes): - [0] u32 protocol_id - [4] u16 sender_peer_id - [6] u8 channel -sender_peer_id: - Unique to each peer. - value 0 (PEER_ID_INEXISTENT) is reserved for making new connections - value 1 (PEER_ID_SERVER) is reserved for server - these constants are defined in constants.h -channel: - The lower the number, the higher the priority is. - Only channels 0, 1 and 2 exist. -*/ -#define BASE_HEADER_SIZE 7 -#define CHANNEL_COUNT 3 -/* -Packet types: - -CONTROL: This is a packet used by the protocol. -- When this is processed, nothing is handed to the user. - Header (2 byte): - [0] u8 type - [1] u8 controltype -controltype and data description: - CONTROLTYPE_ACK - [2] u16 seqnum - CONTROLTYPE_SET_PEER_ID - [2] u16 peer_id_new - CONTROLTYPE_PING - - There is no actual reply, but this can be sent in a reliable - packet to get a reply - CONTROLTYPE_DISCO -*/ -#define TYPE_CONTROL 0 -#define CONTROLTYPE_ACK 0 -#define CONTROLTYPE_SET_PEER_ID 1 -#define CONTROLTYPE_PING 2 -#define CONTROLTYPE_DISCO 3 -#define CONTROLTYPE_ENABLE_BIG_SEND_WINDOW 4 - -/* -ORIGINAL: This is a plain packet with no control and no error -checking at all. -- When this is processed, it is directly handed to the user. - Header (1 byte): - [0] u8 type -*/ -#define TYPE_ORIGINAL 1 -#define ORIGINAL_HEADER_SIZE 1 -/* -SPLIT: These are sequences of packets forming one bigger piece of -data. -- When processed and all the packet_nums 0...packet_count-1 are - present (this should be buffered), the resulting data shall be - directly handed to the user. -- If the data fails to come up in a reasonable time, the buffer shall - be silently discarded. -- These can be sent as-is or atop of a RELIABLE packet stream. - Header (7 bytes): - [0] u8 type - [1] u16 seqnum - [3] u16 chunk_count - [5] u16 chunk_num -*/ -#define TYPE_SPLIT 2 -/* -RELIABLE: Delivery of all RELIABLE packets shall be forced by ACKs, -and they shall be delivered in the same order as sent. This is done -with a buffer in the receiving and transmitting end. -- When this is processed, the contents of each packet is recursively - processed as packets. - Header (3 bytes): - [0] u8 type - [1] u16 seqnum - -*/ -#define TYPE_RELIABLE 3 -#define RELIABLE_HEADER_SIZE 3 -#define SEQNUM_INITIAL 65500 - -/* - A buffer which stores reliable packets and sorts them internally - for fast access to the smallest one. -*/ - -typedef std::list<BufferedPacket>::iterator RPBSearchResult; - -class ReliablePacketBuffer -{ -public: - ReliablePacketBuffer(); - - bool getFirstSeqnum(u16& result); - - BufferedPacket popFirst(); - BufferedPacket popSeqnum(u16 seqnum); - void insert(BufferedPacket &p,u16 next_expected); - - void incrementTimeouts(float dtime); - std::list<BufferedPacket> getTimedOuts(float timeout, - unsigned int max_packets); - - void print(); - bool empty(); - bool containsPacket(u16 seqnum); - RPBSearchResult notFound(); - u32 size(); - - -private: - RPBSearchResult findPacket(u16 seqnum); - - std::list<BufferedPacket> m_list; - u32 m_list_size; - - u16 m_oldest_non_answered_ack; - - JMutex m_list_mutex; -}; - -/* - A buffer for reconstructing split packets -*/ - -class IncomingSplitBuffer -{ -public: - ~IncomingSplitBuffer(); - /* - Returns a reference counted buffer of length != 0 when a full split - packet is constructed. If not, returns one of length 0. - */ - SharedBuffer<u8> insert(BufferedPacket &p, bool reliable); - - void removeUnreliableTimedOuts(float dtime, float timeout); - -private: - // Key is seqnum - std::map<u16, IncomingSplitPacket*> m_buf; - - JMutex m_map_mutex; -}; - -struct OutgoingPacket -{ - u16 peer_id; - u8 channelnum; - SharedBuffer<u8> data; - bool reliable; - bool ack; - - OutgoingPacket(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_, - bool reliable_,bool ack_=false): - peer_id(peer_id_), - channelnum(channelnum_), - data(data_), - reliable(reliable_), - ack(ack_) - { - } -}; - -enum ConnectionCommandType{ - CONNCMD_NONE, - CONNCMD_SERVE, - CONNCMD_CONNECT, - CONNCMD_DISCONNECT, - CONNCMD_DISCONNECT_PEER, - CONNCMD_SEND, - CONNCMD_SEND_TO_ALL, - CONCMD_ACK, - CONCMD_CREATE_PEER, - CONCMD_DISABLE_LEGACY -}; - -struct ConnectionCommand -{ - enum ConnectionCommandType type; - Address address; - u16 peer_id; - u8 channelnum; - Buffer<u8> data; - bool reliable; - bool raw; - - ConnectionCommand(): type(CONNCMD_NONE), peer_id(PEER_ID_INEXISTENT), reliable(false), raw(false) {} - - void serve(Address address_) - { - type = CONNCMD_SERVE; - address = address_; - } - void connect(Address address_) - { - type = CONNCMD_CONNECT; - address = address_; - } - void disconnect() - { - type = CONNCMD_DISCONNECT; - } - void disconnect_peer(u16 peer_id_) - { - type = CONNCMD_DISCONNECT_PEER; - peer_id = peer_id_; - } - void send(u16 peer_id_, u8 channelnum_, - SharedBuffer<u8> data_, bool reliable_) - { - type = CONNCMD_SEND; - peer_id = peer_id_; - channelnum = channelnum_; - data = data_; - reliable = reliable_; - } - void sendToAll(u8 channelnum_, SharedBuffer<u8> data_, bool reliable_) - { - type = CONNCMD_SEND_TO_ALL; - channelnum = channelnum_; - data = data_; - reliable = reliable_; - } - - void ack(u16 peer_id_, u8 channelnum_, SharedBuffer<u8> data_) - { - type = CONCMD_ACK; - peer_id = peer_id_; - channelnum = channelnum_; - data = data_; - reliable = false; - } - - void createPeer(u16 peer_id_, SharedBuffer<u8> data_) - { - type = CONCMD_CREATE_PEER; - peer_id = peer_id_; - data = data_; - channelnum = 0; - reliable = true; - raw = true; - } - - void disableLegacy(u16 peer_id_, SharedBuffer<u8> data_) - { - type = CONCMD_DISABLE_LEGACY; - peer_id = peer_id_; - data = data_; - channelnum = 0; - reliable = true; - raw = true; - } -}; - -class Channel -{ - -public: - u16 readNextIncomingSeqNum(); - u16 incNextIncomingSeqNum(); - - u16 getOutgoingSequenceNumber(bool& successfull); - u16 readOutgoingSequenceNumber(); - bool putBackSequenceNumber(u16); - - u16 readNextSplitSeqNum(); - void setNextSplitSeqNum(u16 seqnum); - - // This is for buffering the incoming packets that are coming in - // the wrong order - ReliablePacketBuffer incoming_reliables; - // This is for buffering the sent packets so that the sender can - // re-send them if no ACK is received - ReliablePacketBuffer outgoing_reliables_sent; - - //queued reliable packets - Queue<BufferedPacket> queued_reliables; - - //queue commands prior splitting to packets - Queue<ConnectionCommand> queued_commands; - - IncomingSplitBuffer incoming_splits; - - Channel(); - ~Channel(); - - void UpdatePacketLossCounter(unsigned int count); - void UpdatePacketTooLateCounter(); - void UpdateBytesSent(unsigned int bytes,unsigned int packages=1); - void UpdateBytesLost(unsigned int bytes); - void UpdateBytesReceived(unsigned int bytes); - - void UpdateTimers(float dtime, bool legacy_peer); - - const float getCurrentDownloadRateKB() - { JMutexAutoLock lock(m_internal_mutex); return cur_kbps; }; - const float getMaxDownloadRateKB() - { JMutexAutoLock lock(m_internal_mutex); return max_kbps; }; - - const float getCurrentLossRateKB() - { JMutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; }; - const float getMaxLossRateKB() - { JMutexAutoLock lock(m_internal_mutex); return max_kbps_lost; }; - - const float getCurrentIncomingRateKB() - { JMutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; }; - const float getMaxIncomingRateKB() - { JMutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; }; - - const float getAvgDownloadRateKB() - { JMutexAutoLock lock(m_internal_mutex); return avg_kbps; }; - const float getAvgLossRateKB() - { JMutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; }; - const float getAvgIncomingRateKB() - { JMutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; }; - - const unsigned int getWindowSize() const { return window_size; }; - - void setWindowSize(unsigned int size) { window_size = size; }; -private: - JMutex m_internal_mutex; - int window_size; - - u16 next_incoming_seqnum; - - u16 next_outgoing_seqnum; - u16 next_outgoing_split_seqnum; - - unsigned int current_packet_loss; - unsigned int current_packet_too_late; - unsigned int current_packet_successfull; - float packet_loss_counter; - - unsigned int current_bytes_transfered; - unsigned int current_bytes_received; - unsigned int current_bytes_lost; - float max_kbps; - float cur_kbps; - float avg_kbps; - float max_incoming_kbps; - float cur_incoming_kbps; - float avg_incoming_kbps; - float max_kbps_lost; - float cur_kbps_lost; - float avg_kbps_lost; - float bpm_counter; - - unsigned int rate_samples; -}; - -class Peer; - -enum PeerChangeType -{ - PEER_ADDED, - PEER_REMOVED -}; -struct PeerChange -{ - PeerChangeType type; - u16 peer_id; - bool timeout; -}; - -class PeerHandler -{ -public: - - PeerHandler() - { - } - virtual ~PeerHandler() - { - } - - /* - This is called after the Peer has been inserted into the - Connection's peer container. - */ - virtual void peerAdded(Peer *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; -}; - -class PeerHelper -{ -public: - PeerHelper(); - PeerHelper(Peer* peer); - ~PeerHelper(); - - PeerHelper& operator=(Peer* peer); - Peer* operator->() const; - bool operator!(); - Peer* operator&() const; - bool operator!=(void* ptr); - -private: - Peer* m_peer; -}; - -class Connection; - -typedef enum { - MIN_RTT, - MAX_RTT, - AVG_RTT, - MIN_JITTER, - MAX_JITTER, - AVG_JITTER -} rtt_stat_type; - -typedef enum { - CUR_DL_RATE, - AVG_DL_RATE, - CUR_INC_RATE, - AVG_INC_RATE, - CUR_LOSS_RATE, - AVG_LOSS_RATE, -} rate_stat_type; - -class Peer { - public: - friend class PeerHelper; - - Peer(Address address_,u16 id_,Connection* connection) : - id(id_), - m_increment_packets_remaining(9), - m_increment_bytes_remaining(0), - m_pending_deletion(false), - m_connection(connection), - address(address_), - m_ping_timer(0.0), - m_last_rtt(-1.0), - m_usage(0), - m_timeout_counter(0.0), - m_last_timeout_check(porting::getTimeMs()), - m_has_sent_with_id(false) - { - m_rtt.avg_rtt = -1.0; - m_rtt.jitter_avg = -1.0; - m_rtt.jitter_max = 0.0; - m_rtt.max_rtt = 0.0; - m_rtt.jitter_min = FLT_MAX; - m_rtt.min_rtt = FLT_MAX; - }; - - virtual ~Peer() { - JMutexAutoLock usage_lock(m_exclusive_access_mutex); - assert(m_usage == 0); - }; - - // Unique id of the peer - u16 id; - - void Drop(); - - virtual void PutReliableSendCommand(ConnectionCommand &c, - unsigned int max_packet_size) {}; - - virtual bool isActive() { return false; }; - - virtual bool getAddress(MTProtocols type, Address& toset) = 0; - - void ResetTimeout() - {JMutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; }; - - bool isTimedOut(float timeout); - - void setSentWithID() - { JMutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; }; - - bool hasSentWithID() - { JMutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; }; - - unsigned int m_increment_packets_remaining; - unsigned int m_increment_bytes_remaining; - - virtual u16 getNextSplitSequenceNumber(u8 channel) { return 0; }; - virtual void setNextSplitSequenceNumber(u8 channel, u16 seqnum) {}; - virtual SharedBuffer<u8> addSpiltPacket(u8 channel, - BufferedPacket toadd, - bool reliable) - { - fprintf(stderr,"Peer: addSplitPacket called, this is supposed to be never called!\n"); - return SharedBuffer<u8>(0); - }; - - 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: - virtual void reportRTT(float rtt) {}; - - void RTTStatistics(float rtt, - std::string profiler_id="", - unsigned int num_samples=1000); - - bool IncUseCount(); - void DecUseCount(); - - JMutex m_exclusive_access_mutex; - - bool m_pending_deletion; - - Connection* m_connection; - - // Address of the peer - Address address; - - // Ping timer - float m_ping_timer; - private: - - struct rttstats { - float jitter_min; - float jitter_max; - float jitter_avg; - float min_rtt; - float max_rtt; - float avg_rtt; - }; - - rttstats m_rtt; - float m_last_rtt; - - // current usage count - unsigned int m_usage; - - // Seconds from last receive - float m_timeout_counter; - - u32 m_last_timeout_check; - - bool m_has_sent_with_id; -}; - -class UDPPeer : public Peer -{ -public: - - friend class PeerHelper; - friend class ConnectionReceiveThread; - friend class ConnectionSendThread; - friend class Connection; - - UDPPeer(u16 a_id, Address a_address, Connection* connection); - virtual ~UDPPeer() {}; - - void PutReliableSendCommand(ConnectionCommand &c, - unsigned int max_packet_size); - - bool isActive() - { return ((hasSentWithID()) && (!m_pending_deletion)); }; - - bool getAddress(MTProtocols type, Address& toset); - - void setNonLegacyPeer(); - - bool getLegacyPeer() - { return m_legacy_peer; } - - u16 getNextSplitSequenceNumber(u8 channel); - void setNextSplitSequenceNumber(u8 channel, u16 seqnum); - - SharedBuffer<u8> addSpiltPacket(u8 channel, - BufferedPacket toadd, - bool reliable); - - -protected: - /* - Calculates avg_rtt and resend_timeout. - rtt=-1 only recalculates resend_timeout - */ - void reportRTT(float rtt); - - void RunCommandQueues( - unsigned int max_packet_size, - unsigned int maxcommands, - unsigned int maxtransfer); - - float getResendTimeout() - { JMutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; } - - void setResendTimeout(float timeout) - { JMutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; } - bool Ping(float dtime,SharedBuffer<u8>& data); - - Channel channels[CHANNEL_COUNT]; - bool m_pending_disconnect; -private: - // This is changed dynamically - float resend_timeout; - - bool processReliableSendCommand( - ConnectionCommand &c, - unsigned int max_packet_size); - - bool m_legacy_peer; -}; - -/* - Connection -*/ - -enum ConnectionEventType{ - CONNEVENT_NONE, - CONNEVENT_DATA_RECEIVED, - CONNEVENT_PEER_ADDED, - CONNEVENT_PEER_REMOVED, - CONNEVENT_BIND_FAILED, -}; - -struct ConnectionEvent -{ - enum ConnectionEventType type; - u16 peer_id; - Buffer<u8> data; - bool timeout; - Address address; - - ConnectionEvent(): type(CONNEVENT_NONE) {} - - std::string describe() - { - switch(type){ - case CONNEVENT_NONE: - return "CONNEVENT_NONE"; - case CONNEVENT_DATA_RECEIVED: - return "CONNEVENT_DATA_RECEIVED"; - case CONNEVENT_PEER_ADDED: - return "CONNEVENT_PEER_ADDED"; - case CONNEVENT_PEER_REMOVED: - return "CONNEVENT_PEER_REMOVED"; - case CONNEVENT_BIND_FAILED: - return "CONNEVENT_BIND_FAILED"; - } - return "Invalid ConnectionEvent"; - } - - void dataReceived(u16 peer_id_, SharedBuffer<u8> data_) - { - type = CONNEVENT_DATA_RECEIVED; - peer_id = peer_id_; - data = data_; - } - void peerAdded(u16 peer_id_, Address address_) - { - type = CONNEVENT_PEER_ADDED; - peer_id = peer_id_; - address = address_; - } - void peerRemoved(u16 peer_id_, bool timeout_, Address address_) - { - type = CONNEVENT_PEER_REMOVED; - peer_id = peer_id_; - timeout = timeout_; - address = address_; - } - void bindFailed() - { - type = CONNEVENT_BIND_FAILED; - } -}; - -class ConnectionSendThread : public JThread { - -public: - friend class UDPPeer; - - ConnectionSendThread(unsigned int max_packet_size, float timeout); - - void * Thread (); - - void Trigger(); - - void setParent(Connection* parent) { - assert(parent != NULL); - m_connection = parent; - } - - void setPeerTimeout(float peer_timeout) - { m_timeout = peer_timeout; } - -private: - void runTimeouts (float dtime); - void rawSend (const BufferedPacket &packet); - bool rawSendAsPacket(u16 peer_id, u8 channelnum, - SharedBuffer<u8> data, bool reliable); - - void processReliableCommand (ConnectionCommand &c); - void processNonReliableCommand (ConnectionCommand &c); - void serve (Address bind_address); - void connect (Address address); - void disconnect (); - void disconnect_peer(u16 peer_id); - void send (u16 peer_id, u8 channelnum, - SharedBuffer<u8> data); - void sendReliable (ConnectionCommand &c); - void sendToAll (u8 channelnum, - SharedBuffer<u8> data); - void sendToAllReliable(ConnectionCommand &c); - - void sendPackets (float dtime); - - void sendAsPacket (u16 peer_id, u8 channelnum, - SharedBuffer<u8> data,bool ack=false); - - void sendAsPacketReliable(BufferedPacket& p, Channel* channel); - - bool packetsQueued(); - - Connection* m_connection; - unsigned int m_max_packet_size; - float m_timeout; - Queue<OutgoingPacket> m_outgoing_queue; - JSemaphore m_send_sleep_semaphore; - - unsigned int m_iteration_packets_avaialble; - unsigned int m_max_commands_per_iteration; - unsigned int m_max_data_packets_per_iteration; - unsigned int m_max_packets_requeued; -}; - -class ConnectionReceiveThread : public JThread { -public: - ConnectionReceiveThread(unsigned int max_packet_size); - - void * Thread (); - - void setParent(Connection* parent) { - assert(parent != NULL); - m_connection = parent; - } - -private: - void receive (); - - // Returns next data from a buffer if possible - // If found, returns true; if not, false. - // If found, sets peer_id and dst - bool getFromBuffers (u16 &peer_id, SharedBuffer<u8> &dst); - - bool checkIncomingBuffers(Channel *channel, u16 &peer_id, - SharedBuffer<u8> &dst); - - /* - Processes a packet with the basic header stripped out. - Parameters: - packetdata: Data in packet (with no base headers) - peer_id: peer id of the sender of the packet in question - channelnum: channel on which the packet was sent - reliable: true if recursing into a reliable packet - */ - SharedBuffer<u8> processPacket(Channel *channel, - SharedBuffer<u8> packetdata, u16 peer_id, - u8 channelnum, bool reliable); - - - Connection* m_connection; -}; - -class Connection -{ -public: - friend class ConnectionSendThread; - friend class ConnectionReceiveThread; - - Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6); - Connection(u32 protocol_id, u32 max_packet_size, float timeout, bool ipv6, - PeerHandler *peerhandler); - ~Connection(); - - /* Interface */ - ConnectionEvent getEvent(); - ConnectionEvent waitEvent(u32 timeout_ms); - void putCommand(ConnectionCommand &c); - - void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; } - void Serve(Address bind_addr); - void Connect(Address address); - bool Connected(); - void Disconnect(); - u32 Receive(u16 &peer_id, SharedBuffer<u8> &data); - void SendToAll(u8 channelnum, SharedBuffer<u8> data, bool reliable); - void Send(u16 peer_id, u8 channelnum, SharedBuffer<u8> data, bool reliable); - u16 GetPeerID(){ return m_peer_id; } - Address GetPeerAddress(u16 peer_id); - float getPeerStat(u16 peer_id, rtt_stat_type type); - float getLocalStat(rate_stat_type type); - const u32 GetProtocolID() const { return m_protocol_id; }; - const std::string getDesc(); - void DisconnectPeer(u16 peer_id); - -protected: - PeerHelper getPeer(u16 peer_id); - PeerHelper getPeerNoEx(u16 peer_id); - u16 lookupPeer(Address& sender); - - u16 createPeer(Address& sender, MTProtocols protocol, int fd); - UDPPeer* createServerPeer(Address& sender); - bool deletePeer(u16 peer_id, bool timeout); - - void SetPeerID(u16 id){ m_peer_id = id; } - - void sendAck(u16 peer_id, u8 channelnum, u16 seqnum); - - void PrintInfo(std::ostream &out); - void PrintInfo(); - - std::list<u16> getPeerIDs(); - - UDPSocket m_udpSocket; - MutexedQueue<ConnectionCommand> m_command_queue; - - void putEvent(ConnectionEvent &e); - - void TriggerSend() - { m_sendThread.Trigger(); } -private: - std::list<Peer*> getPeers(); - - MutexedQueue<ConnectionEvent> m_event_queue; - - u16 m_peer_id; - u32 m_protocol_id; - - std::map<u16, Peer*> m_peers; - JMutex m_peers_mutex; - - ConnectionSendThread m_sendThread; - ConnectionReceiveThread m_receiveThread; - - JMutex m_info_mutex; - - // Backwards compatibility - PeerHandler *m_bc_peerhandler; - int m_bc_receive_timeout; - - bool m_shutting_down; - - u16 m_next_remote_peer_id; -}; - -} // namespace - -#endif - |