#pragma once #include #include #include #include #include #include #include namespace ts { class Command; } namespace tc { namespace connection { namespace server_type { enum value : uint8_t { UNKNOWN, TEASPEAK, TEAMSPEAK }; } class UDPSocket; class ProtocolHandler; class VoiceConnection; class ErrorHandler { public: typedef int16_t error_id; static constexpr error_id error_success = 0; static constexpr error_id error_varianz = 5; std::array error_messages; error_id error_index = 0; std::string get_message(error_id); error_id register_error(const std::string& /* message */); }; class ServerConnection : public Nan::ObjectWrap { friend class ProtocolHandler; public: static NAN_MODULE_INIT(Init); static NAN_METHOD(new_instance); static inline Nan::Persistent & constructor() { static Nan::Persistent my_constructor; return my_constructor; } ServerConnection(); ~ServerConnection() override; NAN_METHOD(connect); NAN_METHOD(connected); NAN_METHOD(disconnect); NAN_METHOD(error_message); NAN_METHOD(send_command); NAN_METHOD(send_voice_data); void send_voice_data(const void* /* buffer */, size_t /* buffer length */, uint8_t /* codec */, bool /* head */); NAN_METHOD(send_voice_data_raw); void initialize(); void finalize(); void close_connection(); /* directly closes connection without notify etc */ std::shared_ptr get_socket() { return this->socket; } private: struct VoicePacket { pipes::buffer voice_data; uint16_t client_id; uint16_t packet_id; uint8_t codec_id; bool flag_head; }; static NAN_METHOD(_connect); static NAN_METHOD(_connected); static NAN_METHOD(_disconnect); static NAN_METHOD(_send_command); static NAN_METHOD(_send_voice_data); static NAN_METHOD(_send_voice_data_raw); static NAN_METHOD(_error_message); static NAN_METHOD(_current_ping); std::unique_ptr callback_connect; std::unique_ptr callback_disconnect; Nan::callback_t call_connect_result; Nan::callback_t call_disconnect_result; Nan::callback_t<> execute_pending_commands; Nan::callback_t<> execute_pending_voice; Nan::callback_t execute_callback_disconnect; ErrorHandler errors; std::shared_ptr socket; std::unique_ptr protocol_handler; std::recursive_timed_mutex disconnect_lock; std::thread event_thread; std::mutex event_lock; std::condition_variable event_condition; bool event_loop_exit = false; /* set to true if we want to exit */ void event_loop(); bool event_loop_execute_connection_close = false; std::chrono::system_clock::time_point next_tick; std::chrono::system_clock::time_point next_resend; void execute_tick(); void schedule_resend(const std::chrono::system_clock::time_point& /* timestamp */); std::mutex pending_commands_lock; std::deque> pending_commands; void _execute_callback_commands(); std::mutex pending_voice_lock; std::deque> pending_voice; void _execute_callback_voice(); uint16_t voice_packet_id = 0; void _execute_callback_disconnect(const std::string&); std::shared_ptr voice_connection; }; } }