77 lines
2.9 KiB
C++
77 lines
2.9 KiB
C++
#include "Renderive_WebSocket_Controller.h"
|
|
|
|
#include "Web_Event_Adapter.h"
|
|
#include "Web_Plot_Session.h"
|
|
#include <renderive/error/Error_Policy.hpp>
|
|
|
|
#include <trantor/utils/Logger.h>
|
|
|
|
#include <exception>
|
|
#include <memory>
|
|
|
|
namespace renderive::web {
|
|
|
|
void Renderive_WebSocket_Controller::handleNewConnection(
|
|
const drogon::HttpRequestPtr&,
|
|
const drogon::WebSocketConnectionPtr& connection) {
|
|
connection->setContext(std::make_shared<Web_Plot_Session>());
|
|
connection->setPingMessage("renderive", std::chrono::seconds(20));
|
|
LOG_INFO << "Renderive WebSocket connected: " << connection->peerAddr().toIpPort();
|
|
}
|
|
|
|
void Renderive_WebSocket_Controller::handleNewMessage(
|
|
const drogon::WebSocketConnectionPtr& connection,
|
|
std::string&& message,
|
|
const drogon::WebSocketMessageType& type) {
|
|
if (type == drogon::WebSocketMessageType::Ping ||
|
|
type == drogon::WebSocketMessageType::Pong ||
|
|
type == drogon::WebSocketMessageType::Close) {
|
|
return;
|
|
}
|
|
if (type != drogon::WebSocketMessageType::Text) {
|
|
connection->shutdown(drogon::CloseCode::kInvalidMessage,
|
|
"Renderive accepts text events only");
|
|
return;
|
|
}
|
|
if (message.size() > 16 * 1024) {
|
|
connection->shutdown(drogon::CloseCode::kMessageTooBig,
|
|
"Renderive event is too large");
|
|
return;
|
|
}
|
|
const auto event = Web_Event_Adapter::decode(message);
|
|
if (!event) {
|
|
connection->shutdown(drogon::CloseCode::kWrongMessageContent,
|
|
"Invalid Renderive event");
|
|
return;
|
|
}
|
|
const auto session = connection->getContext<Web_Plot_Session>();
|
|
if (!session) {
|
|
connection->shutdown(drogon::CloseCode::kUnexpectedCondition,
|
|
"Renderive session is unavailable");
|
|
return;
|
|
}
|
|
try {
|
|
if (auto response = session->handle(*event)) {
|
|
const auto message_type = response->type == Web_Response_Type::Pixels
|
|
? drogon::WebSocketMessageType::Binary
|
|
: drogon::WebSocketMessageType::Text;
|
|
connection->send(response->payload.data(), response->payload.size(),
|
|
message_type);
|
|
}
|
|
} catch (...) {
|
|
static_cast<void>(::renderive::error::capture(
|
|
"handling Renderive WebSocket request", std::current_exception()));
|
|
LOG_ERROR << "Renderive WebSocket session failed";
|
|
connection->shutdown(drogon::CloseCode::kUnexpectedCondition,
|
|
"Renderive rendering failed");
|
|
}
|
|
}
|
|
|
|
void Renderive_WebSocket_Controller::handleConnectionClosed(
|
|
const drogon::WebSocketConnectionPtr& connection) {
|
|
LOG_INFO << "Renderive WebSocket closed: " << connection->peerAddr().toIpPort();
|
|
connection->clearContext();
|
|
}
|
|
|
|
} // namespace renderive::web
|