143 lines
5.9 KiB
C++
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();
|
|
};
|
|
}
|
|
} |