further refactor of how the RESTClient functions (hopefully this will fix the crashes);

pull/25/head
Bryan Biedenkapp 3 years ago
parent cec2816389
commit ad5fc27783

@ -62,7 +62,7 @@ namespace network
class HTTPClient : private Thread { class HTTPClient : private Thread {
public: public:
/// <summary>Initializes a new instance of the HTTPClient class.</summary> /// <summary>Initializes a new instance of the HTTPClient class.</summary>
explicit HTTPClient(const std::string& address, uint16_t port) : HTTPClient(const std::string& address, uint16_t port) :
m_address(address), m_address(address),
m_port(port), m_port(port),
m_connection(nullptr), m_connection(nullptr),
@ -74,6 +74,13 @@ namespace network
} }
/// <summary>Initializes a copy instance of the HTTPClient class.</summary> /// <summary>Initializes a copy instance of the HTTPClient class.</summary>
HTTPClient(const HTTPClient&) = delete; HTTPClient(const HTTPClient&) = delete;
/// <summary>Finalizes a instance of the HTTPClient class.</summary>
~HTTPClient()
{
if (m_connection != nullptr) {
close();
}
}
/// <summary></summary> /// <summary></summary>
HTTPClient& operator=(const HTTPClient&) = delete; HTTPClient& operator=(const HTTPClient&) = delete;
@ -86,8 +93,12 @@ namespace network
} }
/// <summary>Send HTTP request to HTTP server.</summary> /// <summary>Send HTTP request to HTTP server.</summary>
void request(HTTPPayload& request) bool request(HTTPPayload& request)
{ {
if (m_completed) {
return false;
}
asio::post(m_ioContext, [this, request]() { asio::post(m_ioContext, [this, request]() {
std::lock_guard<std::mutex> guard(m_lock); std::lock_guard<std::mutex> guard(m_lock);
{ {
@ -96,19 +107,28 @@ namespace network
} }
} }
}); });
return true;
} }
/// <summary>Opens connection to the network.</summary> /// <summary>Opens connection to the network.</summary>
bool open() bool open()
{ {
m_running = true; if (m_completed) {
return false;
}
return run(); return run();
} }
/// <summary>Closes connection to the network.</summary> /// <summary>Closes connection to the network.</summary>
void close() void close()
{ {
m_running = false; if (m_completed) {
return;
}
m_completed = true;
m_ioContext.stop(); m_ioContext.stop();
if (m_connection != nullptr) { if (m_connection != nullptr) {
@ -124,7 +144,6 @@ namespace network
/// <summary></summary> /// <summary></summary>
virtual void entry() virtual void entry()
{ {
while (m_running) {
asio::ip::tcp::resolver resolver(m_ioContext); asio::ip::tcp::resolver resolver(m_ioContext);
auto endpoints = resolver.resolve(m_address, std::to_string(m_port)); auto endpoints = resolver.resolve(m_address, std::to_string(m_port));
@ -133,28 +152,21 @@ namespace network
// the entry() call will block until all asynchronous operations // the entry() call will block until all asynchronous operations
// have finished // have finished
m_ioContext.run(); m_ioContext.run();
m_ioContext.restart();
}
}
/// <summary>Perform an asynchronous connect operation.</summary>
void connect(asio::ip::basic_resolver_results<asio::ip::tcp>& endpoints)
{
std::lock_guard<std::mutex> guard(m_lock);
{
if (m_connection != nullptr) { if (m_connection != nullptr) {
m_connection->stop(); m_connection->stop();
delete m_connection; delete m_connection;
m_connection = nullptr; m_connection = nullptr;
}
m_socket = asio::ip::tcp::socket(m_ioContext);
} }
/// <summary>Perform an asynchronous connect operation.</summary>
void connect(asio::ip::basic_resolver_results<asio::ip::tcp>& endpoints)
{
asio::connect(m_socket, endpoints); asio::connect(m_socket, endpoints);
m_connection = new ConnectionType(std::move(m_socket), m_requestHandler); m_connection = new ConnectionType(std::move(m_socket), m_requestHandler);
m_connection->start(); m_connection->start();
} }
}
std::string m_address; std::string m_address;
uint16_t m_port; uint16_t m_port;
@ -163,7 +175,7 @@ namespace network
ConnectionType* m_connection; ConnectionType* m_connection;
bool m_running = false; bool m_completed = false;
asio::io_context m_ioContext; asio::io_context m_ioContext;
asio::ip::tcp::socket m_socket; asio::ip::tcp::socket m_socket;

@ -167,12 +167,16 @@ int RESTClient::send(const std::string& address, uint32_t port, const std::strin
typedef network::rest::BasicRequestDispatcher<network::rest::http::HTTPPayload, network::rest::http::HTTPPayload> RESTDispatcherType; typedef network::rest::BasicRequestDispatcher<network::rest::http::HTTPPayload, network::rest::http::HTTPPayload> RESTDispatcherType;
RESTDispatcherType m_dispatcher(RESTClient::responseHandler); RESTDispatcherType m_dispatcher(RESTClient::responseHandler);
HTTPClient<RESTDispatcherType> client(address, port); HTTPClient<RESTDispatcherType>* client = nullptr;
try { try {
if (!client.open()) // setup HTTP client for authentication payload
client = new HTTPClient<RESTDispatcherType>(address, port);
if (!client->open()) {
delete client;
return ERRNO_SOCK_OPEN; return ERRNO_SOCK_OPEN;
client.setHandler(m_dispatcher); }
client->setHandler(m_dispatcher);
// generate password SHA hash // generate password SHA hash
size_t size = password.size(); size_t size = password.size();
@ -203,11 +207,12 @@ int RESTClient::send(const std::string& address, uint32_t port, const std::strin
HTTPPayload httpPayload = HTTPPayload::requestPayload(HTTP_PUT, "/auth"); HTTPPayload httpPayload = HTTPPayload::requestPayload(HTTP_PUT, "/auth");
httpPayload.payload(request); httpPayload.payload(request);
client.request(httpPayload); client->request(httpPayload);
// wait for response and parse // wait for response and parse
if (wait()) { if (wait()) {
client.close(); client->close();
delete client;
return ERRNO_API_CALL_TIMEOUT; return ERRNO_API_CALL_TIMEOUT;
} }
@ -222,19 +227,30 @@ int RESTClient::send(const std::string& address, uint32_t port, const std::strin
token = rsp["token"].get<std::string>(); token = rsp["token"].get<std::string>();
} }
else { else {
client.close(); client->close();
delete client;
return ERRNO_BAD_API_RESPONSE; return ERRNO_BAD_API_RESPONSE;
} }
client->close();
delete client;
// reset the HTTP client and setup for actual payload request
client = new HTTPClient<RESTDispatcherType>(address, port);
if (!client->open())
return ERRNO_SOCK_OPEN;
client->setHandler(m_dispatcher);
// send actual API request // send actual API request
httpPayload = HTTPPayload::requestPayload(method, endpoint); httpPayload = HTTPPayload::requestPayload(method, endpoint);
httpPayload.headers.add("X-DVM-Auth-Token", token); httpPayload.headers.add("X-DVM-Auth-Token", token);
httpPayload.payload(payload); httpPayload.payload(payload);
client.request(httpPayload); client->request(httpPayload);
// wait for response and parse // wait for response and parse
if (wait()) { if (wait()) {
client.close(); client->close();
delete client;
return ERRNO_API_CALL_TIMEOUT; return ERRNO_API_CALL_TIMEOUT;
} }
@ -247,10 +263,13 @@ int RESTClient::send(const std::string& address, uint32_t port, const std::strin
} }
} }
client.close(); client->close();
delete client;
} }
catch (std::exception&) { catch (std::exception&) {
client.close(); if (client != nullptr) {
delete client;
}
return ERRNO_INTERNAL_ERROR; return ERRNO_INTERNAL_ERROR;
} }

Loading…
Cancel
Save

Powered by TurnKey Linux.