Adds immediate migration results
This commit is contained in:
2395 files changed
+357322
-2524
No files matched your search
+320
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* (c) Copyright, Real-Time Innovations, 2024.
|
||||
* All rights reserved.
|
||||
*
|
||||
* No duplications, whole or partial, manual or electronic, may be made
|
||||
* without express written permission. Any such copies, or
|
||||
* revisions thereof, must display this notice unaltered.
|
||||
* This code contains trade secrets of Real-Time Innovations, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _WEBSOCKET_CONNECTION_H_
|
||||
#define _WEBSOCKET_CONNECTION_H_
|
||||
|
||||
#include <civetweb.h>
|
||||
#include <map>
|
||||
|
||||
#include <rti/apputils/StringBuffer.hpp>
|
||||
#include <rti/apputils/http/common/WebSocketUtils.h>
|
||||
#include <rti/apputils/http/common/StatusCode.hpp>
|
||||
#include <rti/apputils/http/common/HttpException.hpp>
|
||||
|
||||
namespace rti { namespace apputils { namespace websocket {
|
||||
|
||||
/*
|
||||
* This class wraps the state of the client connection. Every instance created
|
||||
* from this class must be kept alive until the connection is closed. Whenever
|
||||
* the server receives a new web_wait_factorysocket connection attempt, it
|
||||
* creates a WebSocketConnection instance and this WebSocketConnection will be
|
||||
* attached to the client connection.
|
||||
*
|
||||
* This class has the state of the client connection, the type of content that
|
||||
* the client accepts and the bind ids that each connection have bound.
|
||||
*/
|
||||
class WebSocketConnection {
|
||||
public:
|
||||
explicit WebSocketConnection()
|
||||
: state_(WebSocketStateKind::UNKNOWN),
|
||||
content_type_(WebSocketContentType::UNKNOWN)
|
||||
{ }
|
||||
|
||||
virtual ~WebSocketConnection() = default;
|
||||
|
||||
/**
|
||||
* Overloading the == operator to compare connections.
|
||||
* @param conn A pointer to the connection to compare
|
||||
*/
|
||||
virtual bool operator==(WebSocketConnection *conn) = 0;
|
||||
|
||||
/**
|
||||
* This method returns the state of the connection
|
||||
* @return WebSocketStateKind the current status
|
||||
*/
|
||||
WebSocketStateKind state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the content type accepted for the connection
|
||||
* @return WebSocketContentType
|
||||
*/
|
||||
WebSocketContentType content_type() const
|
||||
{
|
||||
return content_type_;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the state of the connection
|
||||
* @param state WebSocketStateKind the new status
|
||||
*/
|
||||
void state(const WebSocketStateKind& state)
|
||||
{
|
||||
state_ = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the content type accepted for the connection
|
||||
* @param content WebSocketContentType
|
||||
*/
|
||||
void content_type(const WebSocketContentType& content)
|
||||
{
|
||||
content_type_ = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function sends a MG_WEBSOCKET_OPCODE_TEXT message to the user.
|
||||
* @param msg The message string to be sent
|
||||
*/
|
||||
virtual void send(const StringBuffer& msg) = 0;
|
||||
|
||||
/**
|
||||
* This function sends a MG_WEBSOCKET_OPCODE_PONG message to the user.
|
||||
* @param msg The message string to be sent
|
||||
*/
|
||||
virtual void send_pong(const StringBuffer& msg) = 0;
|
||||
|
||||
/**
|
||||
* This function creates the error message to the user.
|
||||
* @param ex Excetion with the info of an issue
|
||||
* @param save_ctx context with that point to the message
|
||||
*/
|
||||
void create_error(
|
||||
RTIXMLSaveContext& save_ctx,
|
||||
const rti::apputils::http::HttpException& ex)
|
||||
{
|
||||
struct DDS_PrintFormat format = DDS_PrintFormat_INITIALIZER;
|
||||
DDS_PrintFormatProperty properties = DDS_PrintFormatProperty_INITIALIZER;
|
||||
DDS_ReturnCode_t retcode = DDS_RETCODE_ERROR;
|
||||
|
||||
if (content_type_ == WebSocketContentType::JSON) {
|
||||
properties.kind = DDS_JSON_PRINT_FORMAT;
|
||||
} else if (content_type_ == WebSocketContentType::XML) {
|
||||
properties.kind = DDS_XML_PRINT_FORMAT;
|
||||
} else {
|
||||
properties.kind = DDS_XML_PRINT_FORMAT;
|
||||
}
|
||||
|
||||
retcode = DDS_PrintFormatProperty_to_print_format(&properties, &format);
|
||||
|
||||
if (retcode != DDS_RETCODE_OK) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
rti::apputils::http::StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Unsupported content type");
|
||||
}
|
||||
|
||||
format.print_top_level_beginning(&format, &save_ctx, "error", 0);
|
||||
|
||||
format.print_primitive_type_beginning(&format, &save_ctx, "code", 1);
|
||||
RTIXMLSaveContext_freeform(
|
||||
&save_ctx,
|
||||
"%d",
|
||||
ex.error_code());
|
||||
format.print_primitive_type_ending(&format, &save_ctx, "code", 1);
|
||||
RTIXMLSaveContext_freeform(&save_ctx, "%s", format.element_separator);
|
||||
|
||||
format.print_primitive_type_beginning(&format, &save_ctx, "message", 1);
|
||||
RTIXMLSaveContext_freeform(
|
||||
&save_ctx,
|
||||
"%sError %s%s",
|
||||
format.string_opening_delimiter,
|
||||
ex.what(),
|
||||
format.string_closing_delimiter);
|
||||
format.print_primitive_type_ending(&format, &save_ctx, "message", 1);
|
||||
RTIXMLSaveContext_freeform(&save_ctx, "%s", format.element_separator);
|
||||
|
||||
format.print_primitive_type_beginning(&format, &save_ctx, "method", 1);
|
||||
RTIXMLSaveContext_freeform(
|
||||
&save_ctx,
|
||||
"%s%s%s",
|
||||
format.string_opening_delimiter,
|
||||
RTI_FUNCTION_NAME,
|
||||
format.string_closing_delimiter);
|
||||
format.print_primitive_type_ending(&format, &save_ctx, "method", 1);
|
||||
|
||||
format.print_top_level_ending(&format, &save_ctx, "error", 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This function sends an error message to the user.
|
||||
* @param msg The error message that the error will have
|
||||
*/
|
||||
void send_error(const rti::apputils::http::HttpException& ex)
|
||||
{
|
||||
StringBuffer buffer;
|
||||
|
||||
RTIXMLSaveContext save_ctx = RTIXMLSaveContext_INITIALIZER;
|
||||
save_ctx.sout = (char*) buffer.c_str();
|
||||
|
||||
if (!RTIOsapiUtility_sizeToUInt32(save_ctx.ssize, buffer.capacity())) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
rti::apputils::http::StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Error allocating string");
|
||||
}
|
||||
|
||||
create_error(save_ctx, ex);
|
||||
if (save_ctx.outputStringLength + 1 > buffer.capacity()) {
|
||||
buffer.ensure_capacity(save_ctx.outputStringLength + 1);
|
||||
|
||||
// Reset save_context
|
||||
RTIXMLSaveContext_initialize(&save_ctx);
|
||||
save_ctx.sout = (char *) buffer.c_str();
|
||||
|
||||
if (!RTIOsapiUtility_sizeToUInt32(save_ctx.ssize, buffer.capacity())) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
rti::apputils::http::StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Error allocating string");
|
||||
}
|
||||
|
||||
create_error(save_ctx, ex);
|
||||
}
|
||||
send(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function creates the request error message to the user.
|
||||
* @param ex RequestExcetion with the info of an issue
|
||||
* @param save_ctx context with that point to the message
|
||||
*/
|
||||
void create_request_error(
|
||||
RTIXMLSaveContext& save_ctx,
|
||||
const RequestException& ex)
|
||||
{
|
||||
struct DDS_PrintFormat format = DDS_PrintFormat_INITIALIZER;
|
||||
DDS_PrintFormatProperty properties = DDS_PrintFormatProperty_INITIALIZER;
|
||||
DDS_ReturnCode_t retcode = DDS_RETCODE_ERROR;
|
||||
|
||||
if (content_type_ == WebSocketContentType::JSON) {
|
||||
properties.kind = DDS_JSON_PRINT_FORMAT;
|
||||
} else if (content_type_ == WebSocketContentType::XML) {
|
||||
properties.kind = DDS_XML_PRINT_FORMAT;
|
||||
} else {
|
||||
properties.kind = DDS_XML_PRINT_FORMAT;
|
||||
}
|
||||
|
||||
retcode = DDS_PrintFormatProperty_to_print_format(&properties, &format);
|
||||
|
||||
if (retcode != DDS_RETCODE_OK) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
rti::apputils::http::StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Unsupported content type");
|
||||
}
|
||||
|
||||
format.print_top_level_beginning(
|
||||
&format,
|
||||
&save_ctx,
|
||||
WEBSOCKET_RESPONSE_NAME,
|
||||
0);
|
||||
|
||||
format.print_primitive_type_beginning(&format, &save_ctx, "return_code", 1);
|
||||
RTIXMLSaveContext_freeform(
|
||||
&save_ctx,
|
||||
"%d",
|
||||
ex.error_code());
|
||||
format.print_primitive_type_ending(&format, &save_ctx, "return_code", 1);
|
||||
RTIXMLSaveContext_freeform(&save_ctx, "%s", format.element_separator);
|
||||
|
||||
format.print_primitive_type_beginning(&format, &save_ctx, "error", 1);
|
||||
RTIXMLSaveContext_freeform(
|
||||
&save_ctx,
|
||||
"%s%s%s",
|
||||
format.string_opening_delimiter,
|
||||
ex.what(),
|
||||
format.string_closing_delimiter);
|
||||
format.print_primitive_type_ending(&format, &save_ctx, "error", 1);
|
||||
RTIXMLSaveContext_freeform(&save_ctx, "%s", format.element_separator);
|
||||
|
||||
format.print_primitive_type_beginning(&format, &save_ctx, "method", 1);
|
||||
RTIXMLSaveContext_freeform(
|
||||
&save_ctx,
|
||||
"%s%s%s",
|
||||
format.string_opening_delimiter,
|
||||
ex.get_method_name(),
|
||||
format.string_closing_delimiter);
|
||||
format.print_primitive_type_ending(&format, &save_ctx, "method", 1);
|
||||
|
||||
format.print_top_level_ending(
|
||||
&format,
|
||||
&save_ctx,
|
||||
WEBSOCKET_RESPONSE_NAME,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function sends an REQUEST error message to the user.
|
||||
* @param msg The error message that the error will have
|
||||
*/
|
||||
void send_request_error(const RequestException& ex)
|
||||
{
|
||||
StringBuffer buffer;
|
||||
|
||||
RTIXMLSaveContext save_ctx = RTIXMLSaveContext_INITIALIZER;
|
||||
|
||||
save_ctx.sout = (char*) buffer.c_str();
|
||||
|
||||
if (!RTIOsapiUtility_sizeToUInt32(save_ctx.ssize, buffer.capacity())) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
rti::apputils::http::StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Error allocating string");
|
||||
}
|
||||
|
||||
create_request_error(save_ctx, ex);
|
||||
if (save_ctx.outputStringLength + 1 > buffer.capacity()) {
|
||||
buffer.ensure_capacity(save_ctx.outputStringLength + 1);
|
||||
|
||||
// Reset save_context
|
||||
RTIXMLSaveContext_initialize(&save_ctx);
|
||||
save_ctx.sout = (char *) buffer.c_str();
|
||||
|
||||
if (!RTIOsapiUtility_sizeToUInt32(save_ctx.ssize, buffer.capacity())) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
rti::apputils::http::StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Error allocating string");
|
||||
}
|
||||
|
||||
create_request_error(save_ctx, ex);
|
||||
}
|
||||
send(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function close a WebSocketConnection.
|
||||
* @param exception with the error message that happend
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
private:
|
||||
WebSocketStateKind state_;
|
||||
WebSocketContentType content_type_;
|
||||
};
|
||||
|
||||
}}} // namespace rti::webdds::websocket
|
||||
#endif // _WEBSOCKET_CONNECTION_H_
|
||||
Reference in new issue
Block a user