From 829d36547516beb0580ad33ba027dcf7dbed4d76 Mon Sep 17 00:00:00 2001 From: Seva Date: Wed, 19 Jun 2019 10:24:51 -0400 Subject: [PATCH] http: detect & handle close connection --- include/opendht/http.h | 7 ++++--- src/http.cpp | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/include/opendht/http.h b/include/opendht/http.h index 76f8adc4..4305bd3f 100644 --- a/include/opendht/http.h +++ b/include/opendht/http.h @@ -1,4 +1,5 @@ /* + * return; * Copyright (C) 2016-2019 Savoir-faire Linux Inc. * Author: Vsevolod Ivanov * @@ -63,7 +64,6 @@ struct Request std::string content; std::shared_ptr parser; std::shared_ptr parser_settings; - }; class ConnectionListener @@ -103,8 +103,6 @@ public: void set_query_address(const std::string ip, const uint16_t port); asio::ip::tcp::resolver::query build_query(); - std::shared_ptr open_conn(); - std::string create_request(const restinio::http_request_header_t header, const restinio::http_header_fields_t header_fields, const restinio::http_connection_header_t connection, @@ -115,6 +113,9 @@ public: std::shared_ptr parser_s); private: + std::shared_ptr open_connection(); + void close_connection(std::shared_ptr conn); + void handle_resolve(const asio::error_code &ec, asio::ip::tcp::resolver::results_type results, std::shared_ptr conn = nullptr); diff --git a/src/http.cpp b/src/http.cpp index 8b1aa882..87eba44d 100644 --- a/src/http.cpp +++ b/src/http.cpp @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -// TODO remove requests connection get closed #include "http.h" @@ -144,19 +143,25 @@ Client::build_query() std::shared_ptr -Client::open_conn() +Client::open_connection() { - using namespace asio::ip; - auto conn = std::make_shared( - connId_, - std::move(asio::ip::tcp::socket{resolver_.get_io_context()}) - ); + auto conn = std::make_shared(connId_, + std::move(asio::ip::tcp::socket{resolver_.get_io_context()})); if (logger_) logger_->d("[connection:%i] created", conn->id()); connId_++; return conn; } +void +Client::close_connection(std::shared_ptr conn) +{ + requests_.erase(conn->id()); + conn->close(); + if (logger_) + logger_->d("[connection:%i] closed", conn->id()); +} + std::string Client::create_request(const restinio::http_request_header_t header, const restinio::http_header_fields_t header_fields, @@ -164,12 +169,15 @@ Client::create_request(const restinio::http_request_header_t header, const std::string body) { std::stringstream request; + // first header request << header.method().c_str() << " " << header.request_target() << " " << "HTTP/" << header.http_major() << "." << header.http_minor() << "\r\n"; + // other headers for (auto header_field: header_fields) request << header_field.name() << ": " << header_field.value() << "\r\n"; + // last connection header std::string conn_str; switch (connection){ @@ -184,11 +192,13 @@ Client::create_request(const restinio::http_request_header_t header, break; } request << "Connection: " << conn_str << "\r\n"; + // body & content-length if (!body.empty()){ request << "Content-Length: " << body.size() << "\r\n\r\n"; request << body; } + // last delim request << "\r\n"; return request.str(); @@ -199,16 +209,19 @@ Client::post_request(std::string request, std::shared_ptr parser, std::shared_ptr parser_s) { - auto conn = open_conn(); + auto conn = open_connection(); + // write the request to buffer std::ostream request_stream(&conn->request_); request_stream << request; + // save things needed later Request req = {}; req.content = request; req.parser = parser; req.parser_settings = parser_s; requests_[conn->id()] = req; + // resolve the query to the server resolver_.async_resolve(build_query(), std::bind(&Client::handle_resolve, this, @@ -236,6 +249,7 @@ Client::handle_resolve(const asio::error_code &ec, if (!conn->is_open()){ if (logger_) logger_->e("[connection:%i] error closed connection", conn->id()); + requests_.erase(conn->id()); return; } // send the request @@ -251,6 +265,7 @@ Client::handle_request(const asio::error_code &ec, std::shared_ptr c if (ec and ec != asio::error::eof){ if (logger_) logger_->e("[connection:%i] error: %s", conn->id(), ec.message().c_str()); + close_connection(conn); return; } // read response @@ -266,13 +281,18 @@ Client::handle_response(const asio::error_code &ec, std::shared_ptr if (logger_) logger_->e("[connection:%i] error handling response: %s", conn->id(), ec.message().c_str()); + return; } - auto &req = requests_[conn->id()]; - + else if ((ec == asio::error::eof) || (ec == asio::error::connection_reset)){ + close_connection(conn); + return; + } + // read the response buffer std::ostringstream str_s; str_s << &conn->response_; // parse the request + auto &req = requests_[conn->id()]; http_parser_execute(req.parser.get(), req.parser_settings.get(), str_s.str().c_str(), str_s.str().size());