178 lines
4.7 KiB
C++
178 lines
4.7 KiB
C++
/*
|
|
* (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
|