Adds immediate migration results
This commit is contained in:
2395 files changed
+357322
-2524
No files matched your search
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* (c) Copyright, Real-Time Innovations, 2022.
|
||||
* 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 HTTP_CLIENT_CONNECTION_HPP
|
||||
#define HTTP_CLIENT_CONNECTION_HPP
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <civetweb.h>
|
||||
|
||||
#include "rti/apputils/ServiceException.hpp"
|
||||
#include "rti/apputils/http/common/Response.hpp"
|
||||
#include "rti/apputils/http/common/HttpUtils.hpp"
|
||||
#include "rti/apputils/http/log/Log.hpp"
|
||||
|
||||
#include "Request.hpp"
|
||||
|
||||
namespace rti { namespace apputils { namespace http { namespace client {
|
||||
|
||||
/**
|
||||
* @brief This class is a wrapper around the SSL configuration for the client.
|
||||
*
|
||||
*/
|
||||
struct SslConfig {
|
||||
SslConfig(
|
||||
bool the_enabled = false,
|
||||
std::string the_client_cert = "",
|
||||
std::string the_server_cert = "")
|
||||
: enabled(the_enabled),
|
||||
client_cert(the_client_cert),
|
||||
server_cert(the_server_cert)
|
||||
{ }
|
||||
|
||||
bool enabled;
|
||||
std::string client_cert;
|
||||
std::string server_cert;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class deal with actual HTTP client requests and
|
||||
* responses to and from CivetWeb.
|
||||
*/
|
||||
class Connection {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Connection object Note that since every request
|
||||
* reconnects the connection, we do not need to connect in the constructor
|
||||
* itself.
|
||||
*
|
||||
* @param host Hostname of the server
|
||||
* @param port Port of the server
|
||||
* @param ssl_config SSL configuration for the client
|
||||
*/
|
||||
Connection(
|
||||
const std::string& host = std::string("localhost"),
|
||||
std::uint16_t port = HTTP_SERVER_DEFAULT_PORT,
|
||||
SslConfig ssl_config = SslConfig())
|
||||
: host_ { host }, port_ { port }, ssl_config_ { ssl_config }
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @brief send an actual HTTP request to CivetWeb. It extracts all
|
||||
* the information from the request and constructs a valid HTTP request
|
||||
* string.
|
||||
*
|
||||
* @param request HTTP request to be sent to the server.
|
||||
*/
|
||||
void send_http_request(const Request& request)
|
||||
{
|
||||
connect();
|
||||
|
||||
// Send HTTP method and URL
|
||||
auto mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"%s %s",
|
||||
method_to_string(request.http_method()).c_str(),
|
||||
request.uri());
|
||||
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
|
||||
// Add URL params to URL
|
||||
if (request.uri_parameters().size() > 0) {
|
||||
mg_result = mg_printf(connection_.get(), "?");
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
for (const auto& uri_param : request.uri_parameters()) {
|
||||
std::array<char, MAX_URI_LENGTH> uri_param_value;
|
||||
uri_param_value.fill('\0');
|
||||
// We need to encode the URI params in case they contain
|
||||
// spaces or any other character that may not be valid in a
|
||||
// URL
|
||||
mg_result = mg_url_encode(
|
||||
uri_param.second.c_str(),
|
||||
uri_param_value.data(),
|
||||
MAX_URI_LENGTH);
|
||||
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_url_encode);
|
||||
|
||||
mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"%s=%s&",
|
||||
uri_param.first.c_str(),
|
||||
uri_param_value.data());
|
||||
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
}
|
||||
|
||||
// Specify HTTP version
|
||||
mg_result = mg_printf(connection_.get(), " HTTP/%s\r\n", HTTP_VERSION);
|
||||
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
|
||||
// Add user-defined headers
|
||||
for (const auto& header : request.headers()) {
|
||||
mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"%s: %s\r\n",
|
||||
header.first.c_str(),
|
||||
header.second.c_str());
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
|
||||
// Add default headers if not defined
|
||||
if (request.header("Content-Length") == nullptr) {
|
||||
mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"Content-Length: %llu\r\n",
|
||||
static_cast<unsigned long long>(request.body().length()));
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
|
||||
if (request.header("Content-Type") == nullptr) {
|
||||
mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"Content-Type: %s\r\n",
|
||||
HTTP_PLAIN_TEXT_CONTENT_TYPE);
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
|
||||
if (request.header("Cache-Control") == nullptr) {
|
||||
mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"Cache-Control: %s\r\n",
|
||||
HTTP_CACHE_CONTROL_NO_CACHE);
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
|
||||
if (request.header("Date") == nullptr) {
|
||||
mg_result = mg_printf(
|
||||
connection_.get(),
|
||||
"Date: %s\r\n",
|
||||
HttpSettings::get_current_date().c_str());
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
|
||||
// Separate headers from body
|
||||
mg_result = mg_printf(connection_.get(), "\r\n");
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result > 0,
|
||||
msg_client_error_printf);
|
||||
|
||||
// Send body of the HTTP request -- if empty it will not write anything
|
||||
mg_result = mg_printf(connection_.get(), "%s", request.body().c_str());
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
mg_result >= 0,
|
||||
msg_client_error_printf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns a Response based on the actual HTTP response received from
|
||||
* CivetWeb. It extracts all the information originally stored in the
|
||||
* mg_connection and transforms it into a valid Response object.
|
||||
*
|
||||
* @param timeout Number of milliseconds to wait for a response. A negative
|
||||
* value means wait indefinitely.
|
||||
*
|
||||
* @return Response object with the response from CivetWeb.
|
||||
*/
|
||||
Response get_http_response(int timeout = HTTP_CLIENT_TIMEOUT_MS)
|
||||
{
|
||||
std::array<char, HTTP_BODY_INITIAL_LENGTH> error_buffer;
|
||||
error_buffer[0] = '\0';
|
||||
|
||||
// Get CivetWeb's response.
|
||||
const auto result = mg_get_response(
|
||||
connection_.get(),
|
||||
error_buffer.data(),
|
||||
error_buffer.size(),
|
||||
timeout);
|
||||
|
||||
// If we timeout trying to get the response, throw an exception.
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
result >= 0,
|
||||
error_buffer.data());
|
||||
|
||||
// Convert CivetWeb's response into a Response
|
||||
const mg_response_info *response_info =
|
||||
mg_get_response_info(connection_.get());
|
||||
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
response_info != nullptr,
|
||||
msg_client_error_get_response_info);
|
||||
|
||||
return Response {
|
||||
static_cast<unsigned short>(response_info->status_code),
|
||||
response_info->status_text,
|
||||
[&] {
|
||||
const auto header =
|
||||
mg_get_header(connection_.get(), "Content-Type");
|
||||
return (header == nullptr) ? "" : header;
|
||||
}(),
|
||||
this->read_content(),
|
||||
[&] {
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
for (int i = 0; i < response_info->num_headers; ++i) {
|
||||
headers.emplace(
|
||||
response_info->http_headers[i].name,
|
||||
response_info->http_headers[i].value);
|
||||
}
|
||||
return headers;
|
||||
}()
|
||||
};
|
||||
}
|
||||
|
||||
std::string read_content(std::size_t chunk_size = 256)
|
||||
{
|
||||
const auto response_info = mg_get_response_info(connection_.get());
|
||||
if (response_info == nullptr) {
|
||||
RTI_THROW_HTTP_EXCEPTION(
|
||||
StatusCode::internal_server_error,
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"Error reading content");
|
||||
}
|
||||
|
||||
if (response_info->content_length >= 0) {
|
||||
return read_content_with_content_length(
|
||||
connection_.get(),
|
||||
static_cast<std::size_t>(response_info->content_length));
|
||||
}
|
||||
|
||||
return read_content_without_content_length(
|
||||
connection_.get(),
|
||||
chunk_size);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief time we connect, we reset the mg_connection. This ensures
|
||||
* that CivetWeb's internal buffers and state is cleaned up. This makes
|
||||
* the Connection easier to use, since it does not need
|
||||
* to be reconnected with every unit test run.
|
||||
*/
|
||||
void connect()
|
||||
{
|
||||
std::array<char, HTTP_BODY_INITIAL_LENGTH> error_buffer;
|
||||
error_buffer[0] = 0;
|
||||
|
||||
if (ssl_config_.enabled) {
|
||||
mg_client_options client_options = create_client_options();
|
||||
connection_.reset(mg_connect_client_secure(
|
||||
&client_options,
|
||||
error_buffer.data(),
|
||||
HTTP_BODY_INITIAL_LENGTH));
|
||||
} else {
|
||||
connection_.reset(mg_connect_client(
|
||||
host_.c_str(),
|
||||
port_,
|
||||
ssl_config_.enabled,
|
||||
error_buffer.data(),
|
||||
HTTP_BODY_INITIAL_LENGTH));
|
||||
}
|
||||
|
||||
|
||||
RTI_SERVICE_CHECK_CONDITION_W_EXTRA_INFO(
|
||||
connection_ != nullptr || error_buffer[0] == 0,
|
||||
error_buffer.data());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This method closes any existing connection.
|
||||
*/
|
||||
struct Disconnect {
|
||||
void operator()(mg_connection *connection) const
|
||||
{
|
||||
mg_close_connection(connection);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This method create a new mg_client_options object with the
|
||||
* information provided by the user.
|
||||
*/
|
||||
mg_client_options create_client_options()
|
||||
{
|
||||
mg_client_options client_options;
|
||||
|
||||
client_options.host = host_.c_str();
|
||||
client_options.port = port_;
|
||||
client_options.client_cert =
|
||||
(ssl_config_.client_cert.empty() || !ssl_config_.enabled)
|
||||
? nullptr
|
||||
: ssl_config_.client_cert.c_str();
|
||||
|
||||
client_options.server_cert =
|
||||
(ssl_config_.server_cert.empty() || !ssl_config_.enabled)
|
||||
? nullptr
|
||||
: ssl_config_.server_cert.c_str();
|
||||
|
||||
client_options.host_name =
|
||||
!ssl_config_.enabled ? nullptr : client_options.host;
|
||||
|
||||
return client_options;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<mg_connection, Disconnect> connection_;
|
||||
std::string host_;
|
||||
std::uint16_t port_;
|
||||
SslConfig ssl_config_;
|
||||
};
|
||||
|
||||
}}}} // namespace rti::apputils::http::client
|
||||
|
||||
#endif // HTTP_CLIENT_CONNECTION_HPP
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* (c) Copyright, Real-Time Innovations, 2022.
|
||||
* 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 HTTP_CLIENT_REQUEST_HPP
|
||||
#define HTTP_CLIENT_REQUEST_HPP
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "rti/apputils/http/common/Method.hpp"
|
||||
#include "rti/apputils/http/common/HttpUtils.hpp"
|
||||
|
||||
namespace rti { namespace apputils { namespace http { namespace client {
|
||||
|
||||
/**
|
||||
* @brief Request class allow users to define their own requests in order to
|
||||
* send them to the server trough the Connection class.
|
||||
*/
|
||||
class Request {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Request empty object
|
||||
*/
|
||||
Request()
|
||||
{
|
||||
uri_.fill('\0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Getter for the HTTP method.
|
||||
*
|
||||
* @return Method object associated to the request.
|
||||
*/
|
||||
Method http_method() const
|
||||
{
|
||||
return http_method_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setter for the HTTP method.
|
||||
*
|
||||
* @param http_method HTTP method (POST, PUT, GET, DELETE, HEAD, PATCH,
|
||||
* OPTIONS).
|
||||
* @return Reference to the Request object.
|
||||
*/
|
||||
Request& http_method(Method http_method)
|
||||
{
|
||||
http_method_ = http_method;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the URL of the HTTP request.
|
||||
*
|
||||
* @return URL of the HTTP request.
|
||||
*/
|
||||
const char *uri() const
|
||||
{
|
||||
return uri_.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the URL of the HTTP request.
|
||||
*
|
||||
* @param uri URL of the HTTP request.
|
||||
* @return Reference to the Request object.
|
||||
*/
|
||||
Request& uri(const char *uri)
|
||||
{
|
||||
std::copy(uri, uri + std::strlen(uri), uri_.data());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the URL of the HTTP request.
|
||||
*
|
||||
* @param uri URL of the HTTP request.
|
||||
* @return Reference to the Request object.
|
||||
*/
|
||||
Request& uri(const std::string& uri)
|
||||
{
|
||||
return this->uri(uri.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of an uri parameter.
|
||||
*
|
||||
* @param name Name of the parameter.
|
||||
* @return const std::string*
|
||||
*/
|
||||
const std::string *uri_parameter(const std::string& name) const
|
||||
{
|
||||
const auto it = uri_parameters_.find(name);
|
||||
if (it == uri_parameters_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets all the uri parameters.
|
||||
*
|
||||
* @return const StringMap&
|
||||
*/
|
||||
const StringMap& uri_parameters() const
|
||||
{
|
||||
return uri_parameters_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets all the uri parameters.
|
||||
*
|
||||
* @param uri_parameters StringMap with all the uri parameters.
|
||||
* @return Request&
|
||||
*/
|
||||
Request& uri_parameters(const StringMap& uri_parameters)
|
||||
{
|
||||
uri_parameters_ = uri_parameters;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of a header.\
|
||||
*
|
||||
* @param name Name of the parameter.
|
||||
* @return const std::string*
|
||||
*/
|
||||
const std::string *header(const std::string& name) const
|
||||
{
|
||||
const auto it = headers_.find(name);
|
||||
if (it == headers_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets all the headers.
|
||||
*
|
||||
* @return const StringMap&
|
||||
*/
|
||||
const StringMap& headers() const
|
||||
{
|
||||
return headers_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets all the headers.
|
||||
*
|
||||
* @param headers StringMap with all the headers.
|
||||
* @return Request&
|
||||
*/
|
||||
Request& headers(const StringMap& headers)
|
||||
{
|
||||
headers_ = headers;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the body of the request.
|
||||
*
|
||||
* @return const std::string&
|
||||
*/
|
||||
const std::string& body() const
|
||||
{
|
||||
return body_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the body of the request.
|
||||
*
|
||||
* @param body Body of the request.
|
||||
* @return Request&
|
||||
*/
|
||||
Request& body(const std::string& body)
|
||||
{
|
||||
body_ = body;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Method http_method_ = Method::http_get;
|
||||
std::array<char, MAX_URI_LENGTH> uri_;
|
||||
StringMap uri_parameters_;
|
||||
StringMap headers_;
|
||||
std::string body_;
|
||||
};
|
||||
|
||||
}}}} // namespace rti::apputils::http::client
|
||||
|
||||
#endif // HTTP_CLIENT_REQUEST_HPP
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* (c) Copyright, Real-Time Innovations, 2020.
|
||||
* 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 CIVETWEBSOCKET_TEST_CONNECTION_CLIENT_H
|
||||
#define CIVETWEBSOCKET_TEST_CONNECTION_CLIENT_H
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "civetweb.h"
|
||||
#include <queue>
|
||||
#include <rti/apputils/http/server/CivetWebSocketConnection.hpp>
|
||||
#include <rti/apputils/log/LogConfig.hpp>
|
||||
#include "log/LogMsg.hpp"
|
||||
|
||||
// #include "utils/WebDDSUtils.h"
|
||||
|
||||
#define CIVETWEB_CLIENT_TIMEOUT_MS 1000
|
||||
#define WEBSOCKET_ERROR_BUFFER_SIZE 10000
|
||||
#define WEBSOCKETinput_buffer__SIZE 10000
|
||||
#define WEBSERVER_DEFAULT_PORT 19020
|
||||
|
||||
namespace rti { namespace apputils { namespace http { namespace client {
|
||||
namespace test {
|
||||
|
||||
class CivetWebSocketClient {
|
||||
public:
|
||||
~CivetWebSocketClient()
|
||||
{
|
||||
mg_close_connection(conn_);
|
||||
}
|
||||
|
||||
static int websocket_client_data_handler(
|
||||
struct mg_connection * /*conn*/,
|
||||
int flags,
|
||||
char *data,
|
||||
size_t data_len,
|
||||
void *user_data)
|
||||
{
|
||||
CivetWebSocketClient *user = NULL;
|
||||
|
||||
if (user_data == NULL) {
|
||||
SERVICELog_exception(
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"No user data defined");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (((unsigned) flags & 0xFu)) {
|
||||
case MG_WEBSOCKET_OPCODE_TEXT:
|
||||
user = reinterpret_cast<CivetWebSocketClient *>(user_data);
|
||||
user->receive(std::string(data, data_len));
|
||||
break;
|
||||
default:
|
||||
SERVICELog_exception(
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"The websocket message code received is not recognize");
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void websocket_client_close_handler(
|
||||
const struct mg_connection *conn,
|
||||
void *user_data)
|
||||
{
|
||||
struct mg_context *context = mg_get_context(conn);
|
||||
|
||||
if (user_data == NULL) {
|
||||
SERVICELog_exception(
|
||||
&RTI_LOG_ANY_FAILURE_s,
|
||||
"No user data defined");
|
||||
return;
|
||||
}
|
||||
|
||||
mg_lock_context(context);
|
||||
|
||||
mg_set_user_connection_data((struct mg_connection *) conn, NULL);
|
||||
|
||||
mg_unlock_context(context);
|
||||
}
|
||||
|
||||
static std::shared_ptr<CivetWebSocketClient> connect(
|
||||
const char *host = "localhost",
|
||||
int port = WEBSERVER_DEFAULT_PORT,
|
||||
bool use_ssl = false,
|
||||
const char *path = "/dds/websocket/test")
|
||||
{
|
||||
StringBuffer error_buffer(WEBSOCKET_ERROR_BUFFER_SIZE);
|
||||
auto result = std::make_shared<CivetWebSocketClient>();
|
||||
|
||||
struct mg_connection *conn = mg_connect_websocket_client(
|
||||
host,
|
||||
port,
|
||||
use_ssl,
|
||||
(char *) error_buffer.c_str_ptr(),
|
||||
WEBSOCKET_ERROR_BUFFER_SIZE,
|
||||
path,
|
||||
NULL,
|
||||
websocket_client_data_handler,
|
||||
websocket_client_close_handler,
|
||||
result.get());
|
||||
|
||||
if (conn == NULL) {
|
||||
SERVICELog_exception(&RTI_LOG_ANY_FAILURE_s, "No Connection");
|
||||
result.reset();
|
||||
return result;
|
||||
}
|
||||
|
||||
result->connection(conn);
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
CivetWebSocketClient() = default;
|
||||
|
||||
CivetWebSocketClient(mg_connection *conn)
|
||||
: conn_(conn)
|
||||
{ }
|
||||
|
||||
void send(const StringBuffer& msg)
|
||||
{
|
||||
mg_websocket_client_write(
|
||||
conn_,
|
||||
MG_WEBSOCKET_OPCODE_TEXT,
|
||||
msg.c_str(),
|
||||
msg.length());
|
||||
}
|
||||
|
||||
void request_close()
|
||||
{
|
||||
mg_websocket_client_write(
|
||||
conn_,
|
||||
MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
void receive(const StringBuffer& buffer)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||
received_buffer_.push(buffer);
|
||||
}
|
||||
|
||||
bool buffer(StringBuffer& buffer)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(mutex_);
|
||||
bool received = false;
|
||||
if (!received_buffer_.empty()) {
|
||||
buffer = received_buffer_.front();
|
||||
received_buffer_.pop();
|
||||
received = true;
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
void connection(mg_connection *conn)
|
||||
{
|
||||
conn_ = conn;
|
||||
}
|
||||
|
||||
private:
|
||||
mg_connection *conn_ = nullptr;
|
||||
std::queue<StringBuffer> received_buffer_;
|
||||
std::recursive_mutex mutex_;
|
||||
};
|
||||
|
||||
}}}}} // namespace rti::apputils::http::client::test
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user