diff --git a/src/network/rest/http/HTTPClient.h b/src/network/rest/http/HTTPClient.h
index 8ee234e8..c58fa76d 100644
--- a/src/network/rest/http/HTTPClient.h
+++ b/src/network/rest/http/HTTPClient.h
@@ -62,7 +62,7 @@ namespace network
class HTTPClient : private Thread {
public:
/// Initializes a new instance of the HTTPClient class.
- explicit HTTPClient(const std::string& address, uint16_t port) :
+ HTTPClient(const std::string& address, uint16_t port) :
m_address(address),
m_port(port),
m_connection(nullptr),
@@ -74,6 +74,13 @@ namespace network
}
/// Initializes a copy instance of the HTTPClient class.
HTTPClient(const HTTPClient&) = delete;
+ /// Finalizes a instance of the HTTPClient class.
+ ~HTTPClient()
+ {
+ if (m_connection != nullptr) {
+ close();
+ }
+ }
///
HTTPClient& operator=(const HTTPClient&) = delete;
@@ -86,8 +93,12 @@ namespace network
}
/// Send HTTP request to HTTP server.
- void request(HTTPPayload& request)
+ bool request(HTTPPayload& request)
{
+ if (m_completed) {
+ return false;
+ }
+
asio::post(m_ioContext, [this, request]() {
std::lock_guard guard(m_lock);
{
@@ -96,19 +107,28 @@ namespace network
}
}
});
+
+ return true;
}
/// Opens connection to the network.
bool open()
{
- m_running = true;
+ if (m_completed) {
+ return false;
+ }
+
return run();
}
/// Closes connection to the network.
void close()
{
- m_running = false;
+ if (m_completed) {
+ return;
+ }
+
+ m_completed = true;
m_ioContext.stop();
if (m_connection != nullptr) {
@@ -124,36 +144,28 @@ namespace network
///
virtual void entry()
{
- while (m_running) {
- asio::ip::tcp::resolver resolver(m_ioContext);
- auto endpoints = resolver.resolve(m_address, std::to_string(m_port));
+ asio::ip::tcp::resolver resolver(m_ioContext);
+ auto endpoints = resolver.resolve(m_address, std::to_string(m_port));
- connect(endpoints);
+ connect(endpoints);
- // the entry() call will block until all asynchronous operations
- // have finished
- m_ioContext.run();
- m_ioContext.restart();
+ // the entry() call will block until all asynchronous operations
+ // have finished
+ m_ioContext.run();
+
+ if (m_connection != nullptr) {
+ m_connection->stop();
+ delete m_connection;
+ m_connection = nullptr;
}
}
/// Perform an asynchronous connect operation.
void connect(asio::ip::basic_resolver_results& endpoints)
{
- std::lock_guard guard(m_lock);
- {
- if (m_connection != nullptr) {
- m_connection->stop();
- delete m_connection;
- m_connection = nullptr;
-
- m_socket = asio::ip::tcp::socket(m_ioContext);
- }
-
- asio::connect(m_socket, endpoints);
- m_connection = new ConnectionType(std::move(m_socket), m_requestHandler);
- m_connection->start();
- }
+ asio::connect(m_socket, endpoints);
+ m_connection = new ConnectionType(std::move(m_socket), m_requestHandler);
+ m_connection->start();
}
std::string m_address;
@@ -163,7 +175,7 @@ namespace network
ConnectionType* m_connection;
- bool m_running = false;
+ bool m_completed = false;
asio::io_context m_ioContext;
asio::ip::tcp::socket m_socket;
diff --git a/src/remote/RESTClient.cpp b/src/remote/RESTClient.cpp
index eca06434..b1be6677 100644
--- a/src/remote/RESTClient.cpp
+++ b/src/remote/RESTClient.cpp
@@ -167,12 +167,16 @@ int RESTClient::send(const std::string& address, uint32_t port, const std::strin
typedef network::rest::BasicRequestDispatcher RESTDispatcherType;
RESTDispatcherType m_dispatcher(RESTClient::responseHandler);
- HTTPClient client(address, port);
+ HTTPClient* client = nullptr;
try {
- if (!client.open())
+ // setup HTTP client for authentication payload
+ client = new HTTPClient(address, port);
+ if (!client->open()) {
+ delete client;
return ERRNO_SOCK_OPEN;
- client.setHandler(m_dispatcher);
+ }
+ client->setHandler(m_dispatcher);
// generate password SHA hash
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.payload(request);
- client.request(httpPayload);
+ client->request(httpPayload);
// wait for response and parse
if (wait()) {
- client.close();
+ client->close();
+ delete client;
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();
}
else {
- client.close();
+ client->close();
+ delete client;
return ERRNO_BAD_API_RESPONSE;
}
+ client->close();
+ delete client;
+
+ // reset the HTTP client and setup for actual payload request
+ client = new HTTPClient(address, port);
+ if (!client->open())
+ return ERRNO_SOCK_OPEN;
+ client->setHandler(m_dispatcher);
+
// send actual API request
httpPayload = HTTPPayload::requestPayload(method, endpoint);
httpPayload.headers.add("X-DVM-Auth-Token", token);
httpPayload.payload(payload);
- client.request(httpPayload);
+ client->request(httpPayload);
// wait for response and parse
if (wait()) {
- client.close();
+ client->close();
+ delete client;
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&) {
- client.close();
+ if (client != nullptr) {
+ delete client;
+ }
return ERRNO_INTERNAL_ERROR;
}