Teaspeak-Server/server/src/client/voice/VoiceClientConnection.h

152 lines
5.4 KiB
C
Raw Normal View History

#pragma once
#include <protocol/ringbuffer.h>
#include <protocol/CompressionHandler.h>
#include <protocol/CryptionHandler.h>
#include <ThreadPool/Thread.h>
#include <ThreadPool/Mutex.h>
#include <protocol/buffers.h>
#include <chrono>
#include <deque>
#include <event.h>
#include <condition_variable>
#include <pipes/buffer.h>
#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<protocol::ClientPacket, 32, std::unique_ptr<protocol::ClientPacket>> packet_buffer_t;
typedef std::array<packet_buffer_t, 8> packet_buffers_t;
explicit VoiceClientConnection(server::VoiceClient*);
virtual ~VoiceClientConnection();
void sendPacket(const std::shared_ptr<protocol::ServerPacket>& 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
*/
2019-10-22 18:39:52 +02:00
bool preprocess_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<std::chrono::system_clock> until = std::chrono::time_point<std::chrono::system_clock>());
protocol::PacketIdManager& getPacketIdManager() { return this->packet_id_manager; }
packet_buffers_t& packet_buffers() { return this->_packet_buffers; }
void reset();
//buffer::SortedBufferQueue<protocol::ClientPacket>** 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<protocol::ClientPacket> next_reassembled_packet(std::unique_lock<std::recursive_timed_mutex>& /* packet channel execute lock */, bool& /* have more */);
2019-10-22 18:39:52 +02:00
/* ---------- Write declarations ---------- */
spin_lock write_queue_lock; /* queue access isn't for long in general */
std::deque<pipes::buffer> write_queue;
2019-10-22 18:39:52 +02:00
struct WritePreprocessCategory {
enum value {
PING_PONG = 0, //Ping/Pongs
ACK = 2,
VOICE_WHISPER = 1, //Voice/Whisper
COMMAND = 3,
INIT = 4,
MAX = INIT
};
inline static value from_type(protocol::PacketType type) {
switch(type) {
case protocol::PING:
case protocol::PONG:
return value::PING_PONG;
case protocol::VOICE:
case protocol::VOICE_WHISPER:
return value::VOICE_WHISPER;
case protocol::ACK:
case protocol::ACK_LOW:
return value::ACK;
case protocol::COMMAND:
case protocol::COMMAND_LOW:
return value::COMMAND;
default:
return value::INIT;
}
}
};
struct WritePreprocessQueue {
int _zero1{0};
bool has_work{false};
std::mutex work_lock{};
spin_lock queue_lock{};
std::deque<std::shared_ptr<protocol::ServerPacket>> queue{};
int _zero{0};
};
std::array<WritePreprocessQueue, WritePreprocessCategory::MAX> write_preprocess_queues{};
/* ---------- Processing ---------- */
/* automatically locked because packets of the same kind should be lock their "work_lock" from their WritePreprocessQueue object */
protocol::PacketIdManager packet_id_manager;
/* this function is thread save :) */
std::atomic<uint8_t> prepare_process_count{0}; /* current thread count preparing a packet */
2019-10-22 18:39:52 +02:00
bool prepare_packet_for_write(std::vector<pipes::buffer> &/* buffers which need to be transferred */, const std::shared_ptr<protocol::ServerPacket> &/* the packet */, std::unique_lock<std::mutex>& /* work lock */);
std::recursive_mutex packet_buffer_lock;
packet_buffers_t _packet_buffers;
uint8_t _packet_buffers_index = 0;
};
}
}