#pragma once #include #include #include #include #include #include #include #include "../../TSServer.h" namespace ts { namespace server { class ConnectedClient; class ConnectedClient; class FileServer; enum FTType { Unknown, TeamSpeak, TeaWeb_SSL, /* not yet decided if the protocol is HTTP or WebSocket */ TeaWeb_SSL_WS, TeaWeb_SSL_HTTP, TeaWeb_HTTP }; class FileClient { friend class FileServer; public: enum TransferState { T_INITIALIZE, T_TRANSFER, T_DONE }; enum ConnectionState { C_CONNECTED, C_DISCONNECTING, C_DISCONNECTED }; struct BandwidthEntry { std::chrono::system_clock::time_point timestamp; uint16_t length = 0; }; FileClient(FileServer* handle, int socketFd); ~FileClient(); void disconnect(std::chrono::milliseconds = std::chrono::milliseconds(5000)); FTType getFTType(){ return this->ftType; } size_t used_bandwidth(); std::string client_prefix(); size_t transferred_bytes(); size_t remaining_bytes(); protected: void disconnectFinal(std::unique_lock& /* tick lock */, bool /* handle flush thread */); bool tick(); bool uploadWriteBytes(const pipes::buffer_view&); void close_file_handle(); bool applyKey(const std::string &); void sendMessage(const pipes::buffer_view&); //Direct methods & IO stuff void sendRawMessage(const pipes::buffer_view&); void handleMessageRead(int, short, void*); void handleMessageWrite(int, short, void*); void handle_ssl_message(const pipes::buffer_view&); /* handeles all decoded SSL messages */ /* http header parser. header must be stored with read buffer! */ void handle_http_header(); /* Final protocol handlers */ void handle_http_message(const pipes::buffer_view&); void handle_ws_message(const pipes::WSMessage&); bool handle_ts_message(); private: FileServer* handle; std::weak_ptr _this; std::recursive_mutex bandwidth_lock; std::deque> bandwidth; sockaddr_storage remote_address; int clientFd; bool event_read_hold = false; ::event* readEvent = nullptr; bool event_write_hold = false; ::event* writeEvent = nullptr; threads::Mutex tickLock; std::recursive_timed_mutex bufferLock; std::deque write_queue; std::deque read_queue; pipes::buffer read_buffer; /* buffer which contains fragments of decoded data, e.g. HTTP request. Access only within tickLock locked */ FTType ftType = FTType::Unknown; pipes::WebSocket ws_handler; pipes::SSL ssl_handler; bool https_upload_init = false; bool http_init = false; /* general flag if the HTTP header has been parsed */ std::shared_ptr client; std::shared_ptr pendingKey = nullptr; std::chrono::time_point last_io_action; std::chrono::time_point connect_timestamp; std::chrono::time_point finished_timestamp; std::fstream* fstream = nullptr; size_t bytesHandled = 0; ConnectionState state_connection = ConnectionState::C_CONNECTED; TransferState state_transfer = TransferState::T_INITIALIZE; size_t availableBytes(); std::string getBytes(size_t); std::string peekBytes(size_t); std::mutex thread_flush_lock; std::thread thread_flush; }; } }