#pragma once #include #include #include #include #include #include #include #include #include #include #include #include "VoiceClient.h" #include "protocol/AcknowledgeManager.h" //#define LOG_ACK_SYSTEM #ifdef LOG_ACK_SYSTEM #define LOG_AUTO_ACK_REQUEST #define LOG_AUTO_ACK_RESPONSE #define LOG_PKT_RESEND #endif //#define PKT_LOG_PING namespace ts { namespace server { class VoiceClient; class VoiceServer; class POWHandler; } namespace connection { class VoiceClientConnection { friend class AcknowledgeManager; friend class server::VoiceServer; friend class server::VoiceClient; friend class server::POWHandler; public: typedef protocol::PacketRingBuffer> packet_buffer_t; typedef std::array packet_buffers_t; explicit VoiceClientConnection(server::VoiceClient*); virtual ~VoiceClientConnection(); void sendPacket(const std::shared_ptr& original_packet, bool copy = false, bool prepare_directly = false); CryptionHandler* getCryptHandler(){ return &crypt_handler; } server::VoiceClient* getClient(){ return client; } #ifdef VC_USE_READ_QUEUE bool handleNextDatagram(); #endif /* * Split packets waiting in write_process_queue and moves the final buffers to writeQueue. * @returns true when there are more packets to prepare */ bool prepare_write_packets(); /* return 2 => Nothing | 1 => More and buffer is set | 0 => Buffer is set, nothing more */ int pop_write_buffer(pipes::buffer& /* buffer */); bool wait_empty_write_and_prepare_queue(std::chrono::time_point until = std::chrono::time_point()); protocol::PacketIdManager& getPacketIdManager() { return this->packet_id_manager; } packet_buffers_t& packet_buffers() { return this->_packet_buffers; } void reset(); //buffer::SortedBufferQueue** getReadQueue() { return this->readTypedQueue; } protected: void handleDatagramReceived(const pipes::buffer_view&); bool verify_encryption(const pipes::buffer_view& /* full packet */); void triggerWrite(); private: server::VoiceClient* client = nullptr; //Decryption / encryption stuff CryptionHandler crypt_handler; CompressionHandler compress_handler; AcknowledgeManager acknowledge_handler; //Handle stuff void execute_handle_packet(const std::chrono::system_clock::time_point& /* scheduled */); std::unique_ptr next_reassembled_packet(std::unique_lock& /* packet channel execute lock */, bool& /* have more */); #ifdef VC_USE_READ_QUEUE std::deque readQueue; #endif spin_lock write_queue_lock; /* queue access isn't for long in general */ std::deque write_queue; spin_lock write_prepare_queue_lock; /* preprocess queue access isn't for long in general */ std::deque> write_prepare_queue; spin_lock packet_id_manager_lock; /* packet id's must be generated in order; Calculating the ID should also not be take too much time */ protocol::PacketIdManager packet_id_manager; /* this function is thread save :) */ std::atomic prepare_process_count{0}; /* current thread count preparing a packet */ bool prepare_packet_for_write(std::vector &/* buffers which need to be transferred */, const std::shared_ptr &/* the packet */); std::recursive_mutex packet_buffer_lock; packet_buffers_t _packet_buffers; uint8_t _packet_buffers_index = 0; }; } }