A lot of query reworking
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "WebClient.h"
|
||||
#include "../shared/RawCommand.h"
|
||||
#include <log/LogUtils.h>
|
||||
#include <src/server/VoiceServer.h>
|
||||
#include <src/InstanceHandler.h>
|
||||
@@ -83,38 +84,29 @@ void WebClient::handleMessageRead(int fd, short, void *) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto pbuffer = buffer::allocate_buffer((size_t) length);
|
||||
pbuffer.write(buffer, length);
|
||||
auto command = command::ReassembledCommand::allocate((size_t) length);
|
||||
memcpy(command->command(), buffer, (size_t) length);
|
||||
|
||||
{
|
||||
lock_guard lock(this->queue_mutex);
|
||||
this->queue_read.push_back(std::move(pbuffer));
|
||||
}
|
||||
|
||||
this->registerMessageProcess();
|
||||
this->command_queue->enqueue_command_execution(command);
|
||||
}
|
||||
|
||||
void WebClient::enqueue_raw_packet(const pipes::buffer_view &msg) {
|
||||
auto buffer = msg.owns_buffer() ? msg.own_buffer() : msg.own_buffer(); /* TODO: Use buffer::allocate_buffer(...) */
|
||||
auto buffer = msg.own_buffer(); /* TODO: Use buffer::allocate_buffer(...) */
|
||||
{
|
||||
lock_guard queue_lock(this->queue_mutex);
|
||||
this->queue_write.push_back(buffer);
|
||||
}
|
||||
{
|
||||
lock_guard lock(this->event_mutex);
|
||||
if(this->writeEvent)
|
||||
if(this->writeEvent) {
|
||||
event_add(this->writeEvent, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
this->connectionStatistics->logOutgoingPacket(stats::ConnectionStatistics::category::COMMAND, buffer.length());
|
||||
}
|
||||
|
||||
void WebClient::registerMessageProcess() {
|
||||
auto weakLock = this->_this;
|
||||
if(serverInstance->getVoiceServerManager()->getState() == VirtualServerManager::STARTED)
|
||||
serverInstance->getVoiceServerManager()->get_executor_loop()->schedule(this->event_handle_packet);
|
||||
}
|
||||
|
||||
inline bool is_ssl_handshake_header(const pipes::buffer_view& buffer) {
|
||||
inline bool is_ssl_handshake_header(const std::string_view& buffer) {
|
||||
if(buffer.length() < 0x05) return false; //Header too small!
|
||||
|
||||
if(buffer[0] != 0x16) return false; //recordType=handshake
|
||||
@@ -125,36 +117,26 @@ inline bool is_ssl_handshake_header(const pipes::buffer_view& buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebClient::processNextMessage(const std::chrono::system_clock::time_point& /* scheduled */) {
|
||||
bool WebClient::process_next_message(const std::string_view &buffer) {
|
||||
lock_guard execute_lock(this->execute_mutex);
|
||||
if(this->state != ConnectionState::INIT_HIGH && this->state != ConnectionState::INIT_LOW && this->state != ConnectionState::CONNECTED)
|
||||
return;
|
||||
|
||||
unique_lock buffer_lock(this->queue_mutex);
|
||||
if(this->queue_read.empty())
|
||||
return;
|
||||
|
||||
auto buffer = this->queue_read.front();
|
||||
this->queue_read.pop_front();
|
||||
bool has_next = !this->queue_read.empty();
|
||||
buffer_lock.unlock();
|
||||
if(this->state != ConnectionState::INIT_HIGH && this->state != ConnectionState::INIT_LOW && this->state != ConnectionState::CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->connectionStatistics->logIncomingPacket(stats::ConnectionStatistics::category::COMMAND, buffer.length());
|
||||
if(!this->ssl_detected) {
|
||||
this->ssl_detected = true;
|
||||
this->ssl_encrypted = is_ssl_handshake_header(buffer);
|
||||
if(this->ssl_encrypted)
|
||||
if(this->ssl_encrypted) {
|
||||
logMessage(this->getServerId(), "[{}] Using encrypted basic connection.", CLIENT_STR_LOG_PREFIX_(this));
|
||||
else
|
||||
} else {
|
||||
logMessage(this->getServerId(), "[{}] Using unencrypted basic connection.", CLIENT_STR_LOG_PREFIX_(this));
|
||||
}
|
||||
}
|
||||
if(this->ssl_encrypted) {
|
||||
this->ssl_handler.process_incoming_data(buffer);
|
||||
this->ssl_handler.process_incoming_data(pipes::buffer_view{buffer.data(), buffer.length()});
|
||||
} else {
|
||||
this->ws_handler.process_incoming_data(buffer);
|
||||
}
|
||||
|
||||
if(has_next) {
|
||||
this->registerMessageProcess();
|
||||
this->ws_handler.process_incoming_data(pipes::buffer_view{buffer.data(), buffer.length()});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -23,7 +23,10 @@ using namespace ts;
|
||||
using namespace ts::server;
|
||||
using namespace ts::protocol;
|
||||
|
||||
WebClient::WebClient(WebControlServer* server, int fd) : SpeakingClient(server->getTS()->getSql(), server->getTS()), handle(server), whisper_handler_{this} {
|
||||
WebClient::WebClient(WebControlServer* server, int fd) :
|
||||
SpeakingClient(server->getTS()->getSql(), server->getTS()),
|
||||
handle{server},
|
||||
whisper_handler_{this} {
|
||||
memtrack::allocated<WebClient>(this);
|
||||
|
||||
assert(server->getTS());
|
||||
@@ -34,7 +37,8 @@ WebClient::WebClient(WebControlServer* server, int fd) : SpeakingClient(server->
|
||||
}
|
||||
|
||||
void WebClient::initialize() {
|
||||
this->event_handle_packet = make_shared<event::ProxiedEventEntry<WebClient>>(dynamic_pointer_cast<WebClient>(this->ref()), &WebClient::processNextMessage);
|
||||
auto ref_this = dynamic_pointer_cast<WebClient>(this->ref());
|
||||
this->command_queue = std::make_unique<ServerCommandQueue>(serverInstance->server_command_executor(), std::make_unique<WebClientCommandHandler>(ref_this));
|
||||
|
||||
int enabled = 1;
|
||||
int disabled = 0;
|
||||
@@ -176,7 +180,7 @@ void WebClient::sendCommand(const ts::command_builder &command, bool low) {
|
||||
this->sendJson(value);
|
||||
} else {
|
||||
auto data = command.build();
|
||||
Command parsed_command = Command::parse(pipes::buffer_view{data.data(), data.length()}, true, false);
|
||||
Command parsed_command = Command::parse(data, true, false);
|
||||
this->sendCommand(parsed_command, low);
|
||||
}
|
||||
}
|
||||
@@ -221,7 +225,6 @@ bool WebClient::close_connection(const std::chrono::system_clock::time_point& ti
|
||||
|
||||
{
|
||||
lock_guard lock(self_lock->queue_mutex);
|
||||
flag_flushed &= self_lock->queue_read.empty();
|
||||
flag_flushed &= self_lock->queue_write.empty();
|
||||
}
|
||||
|
||||
@@ -274,8 +277,8 @@ command_result WebClient::handleCommand(Command &command) {
|
||||
return SpeakingClient::handleCommand(command);
|
||||
}
|
||||
|
||||
void WebClient::tick(const std::chrono::system_clock::time_point& point) {
|
||||
SpeakingClient::tick(point);
|
||||
void WebClient::tick_server(const std::chrono::system_clock::time_point& point) {
|
||||
SpeakingClient::tick_server(point);
|
||||
|
||||
if(this->ping.last_request + seconds(1) < point) {
|
||||
if(this->ping.last_response > this->ping.last_request || this->ping.last_response + this->ping.timeout < point) {
|
||||
@@ -420,6 +423,17 @@ void WebClient::disconnectFinal() {
|
||||
this->handle->unregisterConnection(static_pointer_cast<WebClient>(self_lock));
|
||||
}
|
||||
|
||||
WebClientCommandHandler::WebClientCommandHandler(const std::shared_ptr<WebClient> &client) : client_ref{client} {}
|
||||
|
||||
bool WebClientCommandHandler::handle_command(const std::string_view &command) {
|
||||
auto client = this->client_ref.lock();
|
||||
if(!client) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return client->process_next_message(command);
|
||||
}
|
||||
|
||||
Json::CharReaderBuilder json_reader_builder = []() noexcept {
|
||||
Json::CharReaderBuilder reader_builder;
|
||||
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
#include <json/json.h>
|
||||
#include <EventLoop.h>
|
||||
#include "../shared/WhisperHandler.h"
|
||||
#include "../shared/ServerCommandExecutor.h"
|
||||
|
||||
namespace ts::server {
|
||||
class WebControlServer;
|
||||
class WebClientCommandHandler;
|
||||
|
||||
class WebClient : public SpeakingClient {
|
||||
friend class WebControlServer;
|
||||
friend class WebClientCommandHandler;
|
||||
public:
|
||||
WebClient(WebControlServer*, int socketFd);
|
||||
~WebClient() override;
|
||||
@@ -34,7 +37,7 @@ namespace ts::server {
|
||||
[[nodiscard]] inline std::chrono::nanoseconds client_ping_layer_7() const { return this->js_ping.value; }
|
||||
|
||||
protected:
|
||||
void tick(const std::chrono::system_clock::time_point&) override; /* Every 500ms */
|
||||
void tick_server(const std::chrono::system_clock::time_point&) override; /* Every 500ms */
|
||||
|
||||
void applySelfLock(const std::shared_ptr<WebClient> &cl){ _this = cl; }
|
||||
private:
|
||||
@@ -52,8 +55,6 @@ namespace ts::server {
|
||||
::event* readEvent;
|
||||
::event* writeEvent;
|
||||
|
||||
std::shared_ptr<event::ProxiedEventEntry<WebClient>> event_handle_packet;
|
||||
|
||||
struct {
|
||||
uint8_t current_id{0};
|
||||
std::chrono::system_clock::time_point last_request;
|
||||
@@ -73,7 +74,7 @@ namespace ts::server {
|
||||
} js_ping;
|
||||
|
||||
std::mutex queue_mutex;
|
||||
std::deque<pipes::buffer> queue_read;
|
||||
std::unique_ptr<ServerCommandQueue> command_queue{};
|
||||
std::deque<pipes::buffer> queue_write;
|
||||
threads::Mutex execute_mutex; /* needs to be recursive! */
|
||||
|
||||
@@ -88,8 +89,8 @@ namespace ts::server {
|
||||
void handleMessageWrite(int, short, void*);
|
||||
void enqueue_raw_packet(const pipes::buffer_view& /* buffer */);
|
||||
|
||||
void processNextMessage(const std::chrono::system_clock::time_point& /* scheduled */);
|
||||
void registerMessageProcess();
|
||||
/* TODO: Put the message processing part into the IO loop and not into command processing! */
|
||||
bool process_next_message(const std::string_view& buffer);
|
||||
|
||||
//WS events
|
||||
void onWSConnected();
|
||||
@@ -110,5 +111,16 @@ namespace ts::server {
|
||||
command_result handleCommandWhisperSessionInitialize(Command &command);
|
||||
command_result handleCommandWhisperSessionReset(Command &command);
|
||||
};
|
||||
|
||||
class WebClientCommandHandler : public ts::server::ServerCommandHandler {
|
||||
public:
|
||||
explicit WebClientCommandHandler(const std::shared_ptr<WebClient>& /* client */);
|
||||
|
||||
protected:
|
||||
bool handle_command(const std::string_view &) override;
|
||||
|
||||
private:
|
||||
std::weak_ptr<WebClient> client_ref;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user