Files
Teaspeak-Server/server/src/client/voice/VoiceClientConnection.h
T
2020-03-17 12:08:07 +01:00

143 lines
5.9 KiB
C++

#pragma once
#include <protocol/ringbuffer.h>
#include <protocol/CompressionHandler.h>
#include <protocol/CryptHandler.h>
#include <ThreadPool/Thread.h>
#include <ThreadPool/Mutex.h>
#include <protocol/buffers.h>
#include <chrono>
#include <deque>
#include <event.h>
#include <condition_variable>
#include <utility>
#include <pipes/buffer.h>
#include "VoiceClient.h"
#include "protocol/AcknowledgeManager.h"
#include <protocol/generation.h>
#include "./PacketEncoder.h"
#include "./PacketDecoder.h"
#include "./PingHandler.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;
namespace server::udp {
class Server;
}
}
namespace connection {
enum struct WriteBufferStatus {
EMPTY,
BUFFERS_LEFT,
NO_CHANGES,
UNSET
};
enum struct ClientConnectionState {
INITIALIZING, /* crypto setup */
CONNECTED, /* basic connection has been established */
DISCONNECTING, /* connection is already disconnecting */
DISCONNECTED /* connection has been (maybe successfully) closed */
};
class VoiceClientConnection {
friend class server::VoiceServer;
friend class server::VoiceClient;
public:
explicit VoiceClientConnection(server::server::udp::Server*, const std::shared_ptr<server::VoiceClient>&, int /* socket */);
virtual ~VoiceClientConnection();
void initialize(const std::shared_ptr<VoiceClientConnection>& /* self */);
[[nodiscard]] inline CryptHandler* getCryptHandler(){ return &crypt_handler; }
//[[nodiscard]] inline server::VoiceClient* getClient(){ return client; }
[[nodiscard]] inline server::server::udp::PacketEncoder& packet_encoder() { return this->packet_encoder_; }
[[nodiscard]] inline server::server::udp::PacketDecoder& packet_decoder() { return this->packet_decoder_; }
[[nodiscard]] inline ClientConnectionState connection_state() const { return this->connection_state_; }
void send_packet(const std::shared_ptr<protocol::ServerPacket>& original_packet, bool copy = false, bool prepare_directly = false);
/*
* Split packets waiting in write_process_queue and moves the final buffers to writeQueue.
* @returns true when there are more packets to prepare
*/
bool encode_packets();
/* return 2 => Nothing | 1 => More and buffer is set | 0 => Buffer is set, nothing more */
[[nodiscard]] WriteBufferStatus pop_write_buffer(pipes::buffer& /* buffer */);
/* a flush timout less than now will cause the client to close the connection instantly */
void close_connection(const std::chrono::system_clock::time_point& /* flush timeout */);
void reset();
void tick(); /* called via the UDP server tick */
void force_insert_command(const pipes::buffer_view& /* payload */);
void send_packet_acknowledge(uint16_t /* packet id */, bool /* is command low */);
void send_packet_ping(uint16_t& /* ping id */);
void send_packet_ping_recovery();
protected:
void handle_incoming_datagram(const pipes::buffer_view &buffer);
bool verify_encryption(const pipes::buffer_view& /* full packet */);
void register_for_write();
void register_for_command_handling();
private:
std::weak_ptr<VoiceClientConnection> weak_this{};
server::server::udp::Server* udp_server;
int socket{0};
io::pktinfo_storage address_info{};
VirtualServerId server_id{0};
/* may change at any given time. */
std::shared_ptr<server::VoiceClient> client_handle_{nullptr};
ClientConnectionState connection_state_{ClientConnectionState::INITIALIZING};
std::chrono::system_clock::time_point disconnect_timeout_{};
CryptHandler crypt_handler{};
CompressionHandler compress_handler{};
AcknowledgeManager acknowledge_handler{};
/* ---------- Write declarations ---------- */
spin_lock write_queue_lock; /* queue access isn't for long in general */
std::deque<pipes::buffer> write_queue;
server::server::udp::PacketEncoder packet_encoder_;
server::server::udp::PacketDecoder packet_decoder_;
server::server::udp::PingHandler ping_handler_{};
std::shared_ptr<event::ProxiedEventEntry<VoiceClientConnection>> event_handle_packet;
//Handle stuff
[[nodiscard]] std::string client_log_prefix();
void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */);
/* will be called on the IO thread or if sync has been set directly in any thread */
void handle_encode_error(const std::shared_ptr<protocol::ServerPacket> &/* the packet */, ts::server::server::udp::PacketEncodeResult /* error */, const std::string& /* custom message */);
void handle_encoded_buffers(const std::vector<pipes::buffer>& /* buffers */);
/* will be called on the IO thread */
void handle_decoded_packet(const protocol::ClientPacketParser&);
void handle_decode_error(ts::server::server::udp::PacketDecodeResult /* error */, const std::string& /* custom message */);
void handle_ping_timeout();
};
}
}