2019-07-21 10:43:26 +02:00

133 lines
4.4 KiB
C++

#pragma once
#include <protocol/buffers.h>
#include <poll.h>
#include <fstream>
#include <src/server/file/FileServer.h>
#include <event.h>
#include <pipes/ws.h>
#include <pipes/ssl.h>
#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<threads::Mutex>& /* 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<FileClient> _this;
std::recursive_mutex bandwidth_lock;
std::deque<std::unique_ptr<BandwidthEntry>> 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<pipes::buffer> write_queue;
std::deque<pipes::buffer> 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<ConnectedClient> client;
std::shared_ptr<file::FileTransfereKey> pendingKey = nullptr;
std::chrono::time_point<std::chrono::system_clock> last_io_action;
std::chrono::time_point<std::chrono::system_clock> connect_timestamp;
std::chrono::time_point<std::chrono::system_clock> 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;
};
}
}