diff options
author | Mauro Sardara <msardara+fdio@cisco.com> | 2018-02-16 17:22:53 +0100 |
---|---|---|
committer | Mauro Sardara <msardara+fdio@cisco.com> | 2018-02-16 17:22:53 +0100 |
commit | 953f18b834951680c738e9ce367b5a3eff91ccda (patch) | |
tree | 52bc181e53b9c76db1e14e693f473ca8cfca7250 | |
parent | c5e952d1cadbdf85c976e88ba97ea8bee7e422ab (diff) |
Improvements for HTTP messages processing
Change-Id: Iefcbfa1820bd47fd52475780c68c363a2baa2568
Signed-off-by: Mauro Sardara <msardara+fdio@cisco.com>
35 files changed, 403 insertions, 207 deletions
diff --git a/apps/http/icnet_http_echo_server.cc b/apps/http/icnet_http_echo_server.cc index 223646a2..961c44fd 100644 --- a/apps/http/icnet_http_echo_server.cc +++ b/apps/http/icnet_http_echo_server.cc @@ -19,7 +19,7 @@ namespace icnet { namespace http { -void onPayload(std::shared_ptr<HTTPServerPublisher> &publisher, const uint8_t *buffer, std::size_t size) { +void onPayload(std::shared_ptr<HTTPServerPublisher> &publisher, const uint8_t *buffer, std::size_t size, int request_id) { char *string = (char *) buffer; std::cout << "Received this content:" << std::endl; diff --git a/apps/http/icnet_iget.cc b/apps/http/icnet_iget.cc index d322cc35..4a507864 100644 --- a/apps/http/icnet_iget.cc +++ b/apps/http/icnet_iget.cc @@ -29,19 +29,21 @@ namespace http { void processResponse(std::string &name, HTTPResponse &&response) { + auto &payload = response.getPayload(); + std::string filename = name.substr(1 + name.find_last_of("/")); - std::cout << "Saving to: " << filename << " " << response.size() / 1024 << "kB" << std::endl; + std::cout << "Saving to: " << filename << " " << payload.size() / 1024 << "kB" << std::endl; Time t3 = std::chrono::system_clock::now();; std::ofstream file(filename.c_str(), std::ofstream::binary); - file.write((char *) response.data(), response.size()); + file.write((char *) payload.data(), payload.size()); file.close(); Time t2 = std::chrono::system_clock::now();; TimeDuration dt = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1); TimeDuration dt3 = std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t1); long msec = dt.count(); long msec3 = dt3.count(); - std::cout << "Elapsed Time: " << msec / 1000.0 << " seconds -- " << response.size() * 8 / msec / 1000.0 - << "[Mbps] -- " << response.size() * 8 / msec3 / 1000.0 << "[Mbps]" << std::endl; + std::cout << "Elapsed Time: " << msec / 1000.0 << " seconds -- " << payload.size() * 8 / msec / 1000.0 + << "[Mbps] -- " << payload.size() * 8 / msec3 / 1000.0 << "[Mbps]" << std::endl; } diff --git a/icnet/CMakeLists.txt b/icnet/CMakeLists.txt index 427a3d9f..5d5b3c0c 100644 --- a/icnet/CMakeLists.txt +++ b/icnet/CMakeLists.txt @@ -89,21 +89,25 @@ set(HTTP_HEADER_FILES http/icnet_http_client_connection.h http/icnet_http_server_acceptor.h http/icnet_http_server_publisher.h + http/icnet_http_message.h http/icnet_http_request.h + http/icnet_http_response.h http/icnet_http_facade.h) set(HTTP_SOURCE_FILES http/icnet_http_client_connection.cc http/icnet_http_server_acceptor.cc http/icnet_http_server_publisher.cc - http/icnet_http_request.cc) + http/icnet_http_request.cc + http/icnet_http_response.cc) set(UTILS_HEADER_FILES utils/icnet_utils_array.h utils/icnet_utils_uri.h utils/icnet_utils_daemonizator.h utils/icnet_utils_hash.h - utils/icnet_utils_string_tokenizer.h) + utils/icnet_utils_string_tokenizer.h + utils/icnet_utils_sharable_vector.h) set(UTILS_SOURCE_FILES utils/icnet_utils_array.cc diff --git a/icnet/errors/icnet_errors_malformed_name_exception.cc b/icnet/errors/icnet_errors_malformed_name_exception.cc index 361c211a..b721ebfe 100644 --- a/icnet/errors/icnet_errors_malformed_name_exception.cc +++ b/icnet/errors/icnet_errors_malformed_name_exception.cc @@ -15,8 +15,6 @@ #include "icnet_errors.h" -namespace icnet { - namespace errors { MalformedNameException::MalformedNameException() @@ -27,6 +25,4 @@ char const *MalformedNameException::what() const noexcept { return "Malformed IP address."; } -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_malformed_name_exception.h b/icnet/errors/icnet_errors_malformed_name_exception.h index f714d2b0..c113ee12 100644 --- a/icnet/errors/icnet_errors_malformed_name_exception.h +++ b/icnet/errors/icnet_errors_malformed_name_exception.h @@ -17,8 +17,6 @@ #include <stdexcept> -namespace icnet { - namespace errors { class MalformedNameException : public std::runtime_error { @@ -27,6 +25,4 @@ class MalformedNameException : public std::runtime_error { virtual char const *what() const noexcept override; }; -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_malformed_packet_exception.cc b/icnet/errors/icnet_errors_malformed_packet_exception.cc index 962a6582..5f63e730 100644 --- a/icnet/errors/icnet_errors_malformed_packet_exception.cc +++ b/icnet/errors/icnet_errors_malformed_packet_exception.cc @@ -15,8 +15,6 @@ #include "icnet_errors_malformed_packet_exception.h" -namespace icnet { - namespace errors { MalformedPacketException::MalformedPacketException() @@ -27,6 +25,4 @@ char const *MalformedPacketException::what() const noexcept { return "Malformed IP packet."; } -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_malformed_packet_exception.h b/icnet/errors/icnet_errors_malformed_packet_exception.h index 0420d5c1..42fc7179 100644 --- a/icnet/errors/icnet_errors_malformed_packet_exception.h +++ b/icnet/errors/icnet_errors_malformed_packet_exception.h @@ -17,8 +17,6 @@ #include <stdexcept> -namespace icnet { - namespace errors { class MalformedPacketException : public std::runtime_error { @@ -27,6 +25,4 @@ class MalformedPacketException : public std::runtime_error { virtual char const *what() const noexcept override; }; -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_not_implemented_exception.cc b/icnet/errors/icnet_errors_not_implemented_exception.cc index c58039c9..8a652c74 100644 --- a/icnet/errors/icnet_errors_not_implemented_exception.cc +++ b/icnet/errors/icnet_errors_not_implemented_exception.cc @@ -15,8 +15,6 @@ #include "icnet_errors_not_implemented_exception.h" -namespace icnet { - namespace errors { NotImplementedException::NotImplementedException() @@ -28,6 +26,4 @@ char const *NotImplementedException::what() const noexcept { return "Function not yet implemented."; } -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_not_implemented_exception.h b/icnet/errors/icnet_errors_not_implemented_exception.h index 980ae99f..5711bd1f 100644 --- a/icnet/errors/icnet_errors_not_implemented_exception.h +++ b/icnet/errors/icnet_errors_not_implemented_exception.h @@ -17,8 +17,6 @@ #include <stdexcept> -namespace icnet { - namespace errors { class NotImplementedException : public std::logic_error { @@ -27,6 +25,4 @@ class NotImplementedException : public std::logic_error { virtual char const *what() const noexcept override; }; -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_runtime_exception.cc b/icnet/errors/icnet_errors_runtime_exception.cc index 4853f25c..a180224b 100644 --- a/icnet/errors/icnet_errors_runtime_exception.cc +++ b/icnet/errors/icnet_errors_runtime_exception.cc @@ -15,8 +15,6 @@ #include "icnet_errors_runtime_exception.h" -namespace icnet { - namespace errors { RuntimeException::RuntimeException() @@ -27,6 +25,4 @@ RuntimeException::RuntimeException() // return "Function not yet implemented."; //} -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_runtime_exception.h b/icnet/errors/icnet_errors_runtime_exception.h index 37c6bcb6..7c1e23d6 100644 --- a/icnet/errors/icnet_errors_runtime_exception.h +++ b/icnet/errors/icnet_errors_runtime_exception.h @@ -18,8 +18,6 @@ #include <stdexcept> #include <string> -namespace icnet { - namespace errors { class RuntimeException : public std::runtime_error { @@ -29,6 +27,4 @@ class RuntimeException : public std::runtime_error { : runtime_error(what) {}; }; -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_tokenizer_exception.cc b/icnet/errors/icnet_errors_tokenizer_exception.cc index 1b5e8438..d7da2b0a 100644 --- a/icnet/errors/icnet_errors_tokenizer_exception.cc +++ b/icnet/errors/icnet_errors_tokenizer_exception.cc @@ -15,8 +15,6 @@ #include "icnet_errors_tokenizer_exception.h" -namespace icnet { - namespace errors { TokenizerException::TokenizerException() @@ -28,6 +26,4 @@ char const *TokenizerException::what() const noexcept { return "No more tokens available."; } -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/errors/icnet_errors_tokenizer_exception.h b/icnet/errors/icnet_errors_tokenizer_exception.h index bae9d82a..e849e0db 100644 --- a/icnet/errors/icnet_errors_tokenizer_exception.h +++ b/icnet/errors/icnet_errors_tokenizer_exception.h @@ -17,8 +17,6 @@ #include <stdexcept> -namespace icnet { - namespace errors { class TokenizerException : public std::logic_error { @@ -27,6 +25,4 @@ class TokenizerException : public std::logic_error { virtual char const *what() const noexcept override; }; -} // end namespace errors - -} // end namespace icnet
\ No newline at end of file +} // end namespace errors
\ No newline at end of file diff --git a/icnet/http/icnet_http_client_connection.cc b/icnet/http/icnet_http_client_connection.cc index f07edcc2..d3ccd812 100644 --- a/icnet/http/icnet_http_client_connection.cc +++ b/icnet/http/icnet_http_client_connection.cc @@ -28,7 +28,8 @@ namespace http { using namespace transport; HTTPClientConnection::HTTPClientConnection() - : consumer_(Name("ccnx:"), transport::TransportProtocolAlgorithms::RAAQM) { + : consumer_(Name("ccnx:"), transport::TransportProtocolAlgorithms::RAAQM), timer_(nullptr), + response_(std::make_shared<HTTPResponse>()) { consumer_.setSocketOption(ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY, (ConsumerContentObjectVerificationCallback) std::bind(&HTTPClientConnection::verifyData, @@ -41,9 +42,15 @@ HTTPClientConnection::HTTPClientConnection() this, std::placeholders::_1, std::placeholders::_2)); + + std::shared_ptr<ccnx::Portal> portal; + consumer_.getSocketOption(GeneralTransportOptions::PORTAL, portal); + timer_.reset(new boost::asio::steady_timer(portal->getIoService())); } -HTTPClientConnection &HTTPClientConnection::get(std::string &url, HTTPHeaders headers, HTTPPayload payload) { +HTTPClientConnection &HTTPClientConnection::get(const std::string &url, + HTTPHeaders headers, + HTTPPayload payload) { HTTPRequest request(GET, url, headers, payload); @@ -60,7 +67,7 @@ HTTPClientConnection &HTTPClientConnection::get(std::string &url, HTTPHeaders he // Send content to producer piggybacking it through first interest (to fix) - response_.clear(); + response_->clear(); // Factor icn name @@ -78,12 +85,12 @@ HTTPClientConnection &HTTPClientConnection::get(std::string &url, HTTPHeaders he } HTTPResponse &&HTTPClientConnection::response() { - return std::move(response_); + return std::move(*response_); } void HTTPClientConnection::processPayload(transport::ConsumerSocket &c, std::vector<uint8_t> &&payload) { - response_ = std::move(payload); + *std::static_pointer_cast<std::vector<uint8_t>>(response_) = std::move(payload); } bool HTTPClientConnection::verifyData(transport::ConsumerSocket &c, const ContentObject &contentObject) { @@ -99,10 +106,10 @@ bool HTTPClientConnection::verifyData(transport::ConsumerSocket &c, const Conten void HTTPClientConnection::processLeavingInterest(transport::ConsumerSocket &c, const Interest &interest, std::string &payload) { - if (interest.getName().get(-1).toSegment() == 0) { + // if (interest.getName().get(-1).toSegment() == 0) { Interest &int2 = const_cast<Interest &>(interest); int2.setPayload((const uint8_t *) payload.data(), payload.size()); - } + // } } HTTPClientConnection& HTTPClientConnection::stop() { @@ -116,6 +123,16 @@ transport::ConsumerSocket& HTTPClientConnection::getConsumer() { return consumer_; } +void HTTPClientConnection::setTimeout(const std::chrono::seconds &timeout) { + timer_->cancel(); + timer_->expires_from_now(timeout); + timer_->async_wait([this](boost::system::error_code ec) { + if (!ec) { + consumer_.stop(); + } + }); +} + } } diff --git a/icnet/http/icnet_http_client_connection.h b/icnet/http/icnet_http_client_connection.h index 41a2a4f9..ae52aa3e 100644 --- a/icnet/http/icnet_http_client_connection.h +++ b/icnet/http/icnet_http_client_connection.h @@ -19,9 +19,11 @@ #include "icnet_transport_socket_producer.h" #include "icnet_utils_uri.h" #include "icnet_http_request.h" +#include "icnet_http_response.h" #include "icnet_http_default_values.h" #include <vector> +#include <boost/asio/steady_timer.hpp> #define HTTP_VERSION "1.0" @@ -33,7 +35,9 @@ class HTTPClientConnection { public: HTTPClientConnection(); - HTTPClientConnection &get(std::string &url, HTTPHeaders headers = {}, HTTPPayload payload = {}); + HTTPClientConnection &get(const std::string &url, + HTTPHeaders headers = {}, + HTTPPayload payload = {}); HTTPResponse &&response(); @@ -41,16 +45,19 @@ class HTTPClientConnection { transport::ConsumerSocket &getConsumer(); + void setTimeout(const std::chrono::seconds &timeout); + private: - void processPayload(transport::ConsumerSocket &c, std::vector<uint8_t> &&payload); + void processPayload(transport::ConsumerSocket &c, std::vector<uint8_t> &&response); bool verifyData(transport::ConsumerSocket &c, const transport::ContentObject &contentObject); void processLeavingInterest(transport::ConsumerSocket &c, const transport::Interest &interest, std::string &payload); - HTTPResponse response_; + std::shared_ptr<HTTPResponse> response_; transport::ConsumerSocket consumer_; + std::unique_ptr<boost::asio::steady_timer> timer_; }; } // end namespace http diff --git a/icnet/http/icnet_http_message.h b/icnet/http/icnet_http_message.h new file mode 100644 index 00000000..3d6f9827 --- /dev/null +++ b/icnet/http/icnet_http_message.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "icnet_utils_sharable_vector.h" + +#include <sstream> +#include <vector> +#include <map> + +#define HTTP_VERSION "1.0" + +namespace icnet { + +namespace http { + +typedef enum { + GET, + POST, + PUT, + PATCH, + DELETE +} HTTPMethod; + +static std::map<HTTPMethod, std::string> method_map = { + {GET, "GET"}, {POST, "POST"}, {PUT, "PUT"}, {PATCH, "PATCH"}, {DELETE, "DELETE"}, +}; + +typedef std::map<std::string, std::string> HTTPHeaders; +typedef std::vector<uint8_t> HTTPPayload; + +class HTTPMessage { + public: + + virtual ~HTTPMessage() = default; + + virtual HTTPHeaders &getHeaders() = 0; + + virtual HTTPPayload &getPayload() = 0; + + virtual std::string &getHttpVersion() = 0; + + protected: + HTTPHeaders headers_; + HTTPPayload payload_; + std::string http_version_; +}; + +} // end namespace http + +} // end namespace hicnet
\ No newline at end of file diff --git a/icnet/http/icnet_http_request.cc b/icnet/http/icnet_http_request.cc index f793e893..7710739b 100644 --- a/icnet/http/icnet_http_request.cc +++ b/icnet/http/icnet_http_request.cc @@ -20,17 +20,10 @@ namespace icnet { namespace http { -static std::map<HTTPMethod, std::string> method_map = { - {GET, "GET"}, - {POST, "POST"}, - {PUT, "PUT"}, - {PATCH, "PATCH"}, - {DELETE, "DELETE"}, -}; - -//std::map<HTTPMethod, std::string> method_map - -HTTPRequest::HTTPRequest(HTTPMethod method, std::string &url, HTTPHeaders &headers, HTTPPayload &payload) { +HTTPRequest::HTTPRequest(HTTPMethod method, + const std::string &url, + const HTTPHeaders &headers, + const HTTPPayload &payload) { utils::Uri uri; uri.parse(url); @@ -39,6 +32,7 @@ HTTPRequest::HTTPRequest(HTTPMethod method, std::string &url, HTTPHeaders &heade protocol_ = uri.getProtocol(); locator_ = uri.getLocator(); port_ = uri.getPort(); + http_version_ = HTTP_VERSION; headers_ = headers; payload_ = payload; @@ -99,6 +93,10 @@ std::string &HTTPRequest::getRequestString() { return request_string_; } +std::string &HTTPRequest::getHttpVersion() { + return http_version_; +} + } }
\ No newline at end of file diff --git a/icnet/http/icnet_http_request.h b/icnet/http/icnet_http_request.h index 985d7628..ec4a3d6f 100644 --- a/icnet/http/icnet_http_request.h +++ b/icnet/http/icnet_http_request.h @@ -15,6 +15,9 @@ #pragma once +#include "icnet_utils_sharable_vector.h" +#include "icnet_http_message.h" + #include <sstream> #include <vector> #include <map> @@ -25,23 +28,11 @@ namespace icnet { namespace http { -typedef enum { - GET, - POST, - PUT, - PATCH, - DELETE -} HTTPMethod; - -typedef std::map<std::string, std::string> HTTPHeaders; -typedef std::vector<uint8_t> HTTPPayload; -typedef std::vector<uint8_t> HTTPResponse; - -class HTTPRequest { +class HTTPRequest : public HTTPMessage { public: HTTPRequest(HTTPMethod method, - std::string &url, HTTPHeaders &headers, HTTPPayload &payload); + const std::string &url, const HTTPHeaders &headers, const HTTPPayload &payload); std::string &getQueryString(); @@ -55,9 +46,11 @@ class HTTPRequest { std::string &getRequestString(); - HTTPHeaders &getHeaders(); + HTTPHeaders &getHeaders() override; + + HTTPPayload &getPayload() override; - HTTPPayload &getPayload(); + std::string &getHttpVersion() override; private: std::string query_string_, path_, protocol_, locator_, port_; diff --git a/icnet/http/icnet_http_response.cc b/icnet/http/icnet_http_response.cc new file mode 100644 index 00000000..c9d31738 --- /dev/null +++ b/icnet/http/icnet_http_response.cc @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "icnet_http_response.h" +#include "icnet_errors.h" + +#include <algorithm> + +#include <cstring> + +namespace icnet { + +namespace http { + +HTTPResponse::HTTPResponse() { +} + +HTTPResponse::HTTPResponse(const HTTPHeaders &headers, const HTTPPayload &payload) { + headers_ = headers; + payload_ = payload; +} + +HTTPHeaders &HTTPResponse::getHeaders() { + parse(); + return headers_; +} + +HTTPPayload &HTTPResponse::getPayload() { + parse(); + return payload_; +} + +bool HTTPResponse::parseHeaders() { + const char *crlf2 = "\r\n\r\n"; + auto it = std::search(this->begin(), this->end(), crlf2, crlf2 + strlen(crlf2)); + + if (it != end()) { + std::stringstream ss; + ss.str(std::string(begin(), it)); + + std::string line; + getline(ss, line); + std::istringstream line_s(line); + std::string _http_version; + std::string http_version; + + line_s >> _http_version; + std::size_t separator; + if ((separator = _http_version.find('/')) != std::string::npos) { + if (_http_version.substr(0, separator) != "HTTP") { + return false; + } + http_version_ = line.substr(separator + 1, _http_version.length() - separator - 1); + } else { + return false; + } + + std::string status_code, status_string; + + line_s >> status_code_; + line_s >> status_string; + + auto _it = std::search(line.begin(), line.end(), status_string.begin(), status_string.end()); + + status_string_ = std::string(_it, line.end() - 1); + + std::size_t param_end; + std::size_t value_start; + while (getline(ss, line)) { + if ((param_end = line.find(':')) != std::string::npos) { + value_start = param_end + 1; + if ((value_start) < line.size()) { + if (line[value_start] == ' ') { + value_start++; + } + if (value_start < line.size()) { + headers_[line.substr(0, param_end)] = line.substr(value_start, line.size() - value_start - 1); + } + } + } else { + return false; + } + } + } + + return true; +} + +void HTTPResponse::parse() { + if (!parseHeaders()) { + throw errors::RuntimeException("Malformed HTTP response"); + } + + if (payload_.empty()) { + const char *crlf2 = "\r\n\r\n"; + auto it = std::search(this->begin(), this->end(), crlf2, crlf2 + strlen(crlf2)); + + if (it != this->end()) { + erase(begin(), it + strlen(crlf2)); + payload_ = std::move(*dynamic_cast<std::vector<uint8_t> *>(this)); + } + } +} + +std::string &HTTPResponse::getStatusCode() { + return status_code_; +} + +std::string &HTTPResponse::getStatusString() { + return status_string_; +} + +std::string &HTTPResponse::getHttpVersion() { + return http_version_; +} + +} + +}
\ No newline at end of file diff --git a/icnet/http/icnet_http_response.h b/icnet/http/icnet_http_response.h new file mode 100644 index 00000000..b925e1e3 --- /dev/null +++ b/icnet/http/icnet_http_response.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "icnet_utils_sharable_vector.h" +#include "icnet_http_message.h" +#include "icnet_utils_array.h" + +#include <sstream> +#include <vector> +#include <map> + +namespace icnet { + +namespace http { + +class HTTPResponse : public HTTPMessage, public utils::SharableVector<uint8_t> { + public: + + HTTPResponse(const HTTPHeaders &headers, const HTTPPayload &payload); + + HTTPResponse(); + + HTTPHeaders &getHeaders() override; + + HTTPPayload &getPayload() override; + + std::string &getStatusCode(); + + std::string &getStatusString(); + + std::string &getHttpVersion() override; + + void parse(); + + private: + bool parseHeaders(); + + private: + std::string status_code_; + std::string status_string_; +}; + +} // end namespace http + +} // end namespace hicnet
\ No newline at end of file diff --git a/icnet/http/icnet_http_server_acceptor.cc b/icnet/http/icnet_http_server_acceptor.cc index 9406955d..424d380f 100644 --- a/icnet/http/icnet_http_server_acceptor.cc +++ b/icnet/http/icnet_http_server_acceptor.cc @@ -106,65 +106,29 @@ void HTTPServerAcceptor::processIncomingInterest(transport::ProducerSocket &p, c if (method == "GET") { HTTPRequest request(GET, url, headers, payload); - auto publisher = std::make_shared<HTTPServerPublisher>(request_name); - callback_(publisher, (uint8_t *) request.getRequestString().data(), request.getRequestString().size()); + + int request_id = utils::Hash::hash32(request.getRequestString().data(), request.getRequestString().size()); + + if (publishers_.find(request_id) != publishers_.end()) { + if (publishers_[request_id]) { + publishers_[request_id]->getProducer().onInterest(interest.getName(), interest); + return; + } + } else { + std::cout << "Request ID" << request_id << std::endl; + } + + publishers_[request_id] = std::make_shared<HTTPServerPublisher>(request_name); + callback_(publishers_[request_id], + (uint8_t *) request.getRequestString().data(), + request.getRequestString().size(), + request_id); } } -//void HTTPServerConnection::sendResponse() { -// -// std::thread t([]() { -// -// // Get the name of the HTTP method to compute -// std::string method = request_name.get(1).toString(); -// std::transform(method.begin(), method.end(), method.begin(), ::toupper); -// std::string path; -// -// // This is done for getting rid of useless name components such as ccnx: or ndn: -// if (request_name.getSegmentCount() > 2) { -// std::string rawPath = request_name.getSubName(2).toString(); -// std::size_t pos = rawPath.find("/"); -// path = rawPath.substr(pos); -// } -// -// // Create new producer -// -// // Create timer for response availability -// std::shared_ptr<core::Portal> portal; -// po->getSocketOption(icnet::GeneralTransportOptions::PORTAL, portal); -// boost::asio::io_service &ioService = portal->getIoService(); -// -// boost::asio::deadline_timer t(ioService, boost::posix_time::seconds(5)); -// -// std::function<void(const boost::system::error_code e)> -// wait_callback = [&ioService](const boost::system::error_code e) { -// if (!e) { -// // Be sure to delete the timer before the io_service, otherwise we'll get some strange behavior! -// ioService.stop(); -// } -// }; -// -// std::function<void(transport::ProducerSocket, const core::Interest &interest)> -// interest_enter_callback = [this, &wait_callback, &t] -// (transport::ProducerSocket &p, const core::Interest &interest) { -// t.cancel(); -// t.expires_from_now(boost::posix_time::seconds(5)); -// t.async_wait(wait_callback); -// }; -// -// p->setSocketOption(transport::ProducerCallbacksOptions::INTEREST_INPUT, -// (transport::ProducerInterestCallback) interest_enter_callback); -// -// t.async_wait(wait_callback); -// -// p->serveForever(); -// -// std::unique_lock<std::mutex> lock(thread_list_mtx_); -// icn_producers_.erase(request_name); -// }); -// -// t.detach(); -//} +std::map<int, std::shared_ptr<HTTPServerPublisher>>& HTTPServerAcceptor::getPublishers() { + return publishers_; +} } diff --git a/icnet/http/icnet_http_server_acceptor.h b/icnet/http/icnet_http_server_acceptor.h index 2d0b7f25..f5af47e8 100644 --- a/icnet/http/icnet_http_server_acceptor.h +++ b/icnet/http/icnet_http_server_acceptor.h @@ -31,7 +31,7 @@ namespace http { //typedef std::vector<uint8_t> HTTPResponse; typedef std::vector<uint8_t> HttpRequest; -typedef std::function<void(std::shared_ptr<HTTPServerPublisher> &, const uint8_t *, std::size_t)> OnHttpRequest; +typedef std::function<void(std::shared_ptr<HTTPServerPublisher> &, const uint8_t *, std::size_t, int request_id)> OnHttpRequest; class HTTPServerAcceptor { public: @@ -42,11 +42,7 @@ class HTTPServerAcceptor { HttpRequest &&request(); -// void asyncSendResponse(); - -// HTTPClientConnection& get(std::string &url, HTTPHeaders headers = {}, HTTPPayload payload = {}); -// -// HTTPResponse&& response(); + std::map<int, std::shared_ptr<HTTPServerPublisher>>& getPublishers(); private: @@ -55,6 +51,8 @@ class HTTPServerAcceptor { OnHttpRequest callback_; HttpRequest request_; std::shared_ptr<transport::ProducerSocket> acceptor_producer_; + + std::map<int, std::shared_ptr<HTTPServerPublisher>> publishers_; }; } // end namespace http diff --git a/icnet/http/icnet_http_server_publisher.cc b/icnet/http/icnet_http_server_publisher.cc index 82c90051..716eaa7b 100644 --- a/icnet/http/icnet_http_server_publisher.cc +++ b/icnet/http/icnet_http_server_publisher.cc @@ -36,10 +36,14 @@ HTTPServerPublisher& HTTPServerPublisher::attachPublisher() { return *this; } -HTTPServerPublisher &HTTPServerPublisher::setTimeout(uint32_t timeout) { +transport::ProducerSocket& HTTPServerPublisher::getProducer() { + return *producer_; +} + +HTTPServerPublisher &HTTPServerPublisher::setTimeout(const std::chrono::milliseconds &timeout, bool timeout_renewal) { std::shared_ptr<transport::Portal> portal; producer_->getSocketOption(transport::GeneralTransportOptions::PORTAL, portal); - timer_ = std::unique_ptr<boost::asio::deadline_timer>(new boost::asio::deadline_timer(portal->getIoService(), boost::posix_time::seconds(timeout))); + timer_ = std::unique_ptr<boost::asio::steady_timer>(new boost::asio::steady_timer(portal->getIoService(), timeout)); wait_callback_ = [this](const boost::system::error_code e) { if (!e) { @@ -47,14 +51,16 @@ HTTPServerPublisher &HTTPServerPublisher::setTimeout(uint32_t timeout) { } }; - interest_enter_callback_ = [this, timeout](transport::ProducerSocket &p, const transport::Interest &interest) { - this->timer_->cancel(); - this->timer_->expires_from_now(boost::posix_time::seconds(timeout)); - this->timer_->async_wait(wait_callback_); - }; + if (timeout_renewal) { + interest_enter_callback_ = [this, timeout](transport::ProducerSocket &p, const transport::Interest &interest) { + this->timer_->cancel(); + this->timer_->expires_from_now(timeout); + this->timer_->async_wait(wait_callback_); + }; - producer_->setSocketOption(transport::ProducerCallbacksOptions::INTEREST_INPUT, - (transport::ProducerInterestCallback) interest_enter_callback_); + producer_->setSocketOption(transport::ProducerCallbacksOptions::INTEREST_INPUT, + (transport::ProducerInterestCallback) interest_enter_callback_); + } timer_->async_wait(wait_callback_); diff --git a/icnet/http/icnet_http_server_publisher.h b/icnet/http/icnet_http_server_publisher.h index 7162f4d1..7c96ce15 100644 --- a/icnet/http/icnet_http_server_publisher.h +++ b/icnet/http/icnet_http_server_publisher.h @@ -20,6 +20,7 @@ #include "icnet_http_default_values.h" #include <vector> +#include <boost/asio/steady_timer.hpp> #include <functional> #ifdef __ANDROID__ @@ -51,16 +52,18 @@ class HTTPServerPublisher { void stop(); - HTTPServerPublisher &setTimeout(uint32_t timeout); + HTTPServerPublisher &setTimeout(const std::chrono::milliseconds &timeout, bool timeout_renewal); HTTPServerPublisher &attachPublisher(); + transport::ProducerSocket& getProducer(); + private: void processIncomingInterest(transport::ProducerSocket &p, const transport::Interest &interest); transport::Name content_name_; - std::unique_ptr<boost::asio::deadline_timer> timer_; + std::unique_ptr<boost::asio::steady_timer> timer_; std::unique_ptr<transport::ProducerSocket> producer_; transport::ProducerInterestCallback interest_enter_callback_; DeadlineTimerCallback wait_callback_; diff --git a/icnet/utils/icnet_utils_array.cc b/icnet/utils/icnet_utils_array.cc index 413119cb..a395ddd8 100644 --- a/icnet/utils/icnet_utils_array.cc +++ b/icnet/utils/icnet_utils_array.cc @@ -15,8 +15,6 @@ #include "icnet_utils_array.h" -namespace icnet { - namespace utils { Array::Array(const void *array, size_t size) { @@ -47,6 +45,4 @@ Array &Array::setSize(std::size_t size) { return *this; } -} - }
\ No newline at end of file diff --git a/icnet/utils/icnet_utils_array.h b/icnet/utils/icnet_utils_array.h index f13c0b47..c356190e 100644 --- a/icnet/utils/icnet_utils_array.h +++ b/icnet/utils/icnet_utils_array.h @@ -17,8 +17,6 @@ #include <cstddef> -namespace icnet { - namespace utils { class Array { @@ -41,5 +39,3 @@ class Array { }; } - -} diff --git a/icnet/utils/icnet_utils_daemonizator.cc b/icnet/utils/icnet_utils_daemonizator.cc index 2bb6dd05..061573d1 100644 --- a/icnet/utils/icnet_utils_daemonizator.cc +++ b/icnet/utils/icnet_utils_daemonizator.cc @@ -20,8 +20,6 @@ #include <iostream> #include <sys/stat.h> -namespace icnet { - namespace utils { void Daemonizator::daemonize() { @@ -70,5 +68,3 @@ void Daemonizator::daemonize() { } } - -} diff --git a/icnet/utils/icnet_utils_daemonizator.h b/icnet/utils/icnet_utils_daemonizator.h index 20cd80bb..6297c836 100644 --- a/icnet/utils/icnet_utils_daemonizator.h +++ b/icnet/utils/icnet_utils_daemonizator.h @@ -15,8 +15,6 @@ #pragma once -namespace icnet { - namespace utils { class Daemonizator { @@ -24,6 +22,4 @@ class Daemonizator { static void daemonize(); }; -} - }
\ No newline at end of file diff --git a/icnet/utils/icnet_utils_hash.cc b/icnet/utils/icnet_utils_hash.cc index 39dd0229..51a0f639 100644 --- a/icnet/utils/icnet_utils_hash.cc +++ b/icnet/utils/icnet_utils_hash.cc @@ -15,8 +15,6 @@ #include "icnet_utils_hash.h" -namespace icnet { - namespace utils { uint32_t Hash::hash32(const void *data, std::size_t len) { @@ -59,6 +57,4 @@ uint64_t Hash::cumulativeHash64(const void *data, std::size_t len, uint64_t last return hash; } -} - }
\ No newline at end of file diff --git a/icnet/utils/icnet_utils_hash.h b/icnet/utils/icnet_utils_hash.h index 9ae01f39..26ae9c6f 100644 --- a/icnet/utils/icnet_utils_hash.h +++ b/icnet/utils/icnet_utils_hash.h @@ -18,8 +18,6 @@ #include <cstdint> #include <cstddef> -namespace icnet { - namespace utils { //const uint32_t FNV1A_PRIME_32 = 0x01000193; @@ -37,6 +35,4 @@ class Hash { }; -} - }
\ No newline at end of file diff --git a/icnet/utils/icnet_utils_sharable_vector.h b/icnet/utils/icnet_utils_sharable_vector.h new file mode 100644 index 00000000..d78a9a6a --- /dev/null +++ b/icnet/utils/icnet_utils_sharable_vector.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <vector> +#include <memory> + +namespace utils { + +template<class T> +class SharableVector : public std::vector<T>, public std::enable_shared_from_this<SharableVector<T>> { + public: + virtual ~SharableVector() {}; +}; + +} diff --git a/icnet/utils/icnet_utils_string_tokenizer.cc b/icnet/utils/icnet_utils_string_tokenizer.cc index ead1052a..19d76c3e 100644 --- a/icnet/utils/icnet_utils_string_tokenizer.cc +++ b/icnet/utils/icnet_utils_string_tokenizer.cc @@ -17,8 +17,6 @@ #include "icnet_utils_string_tokenizer.h" #include "icnet_errors.h" -namespace icnet { - namespace utils { StringTokenizer::StringTokenizer(const std::string &str) @@ -48,5 +46,4 @@ std::string StringTokenizer::nextToken() { return token; } -} }
\ No newline at end of file diff --git a/icnet/utils/icnet_utils_string_tokenizer.h b/icnet/utils/icnet_utils_string_tokenizer.h index 7dc6b458..c1111b49 100644 --- a/icnet/utils/icnet_utils_string_tokenizer.h +++ b/icnet/utils/icnet_utils_string_tokenizer.h @@ -17,8 +17,6 @@ #include <string> -namespace icnet { - namespace utils { class StringTokenizer { @@ -34,5 +32,3 @@ class StringTokenizer { }; } - -} diff --git a/icnet/utils/icnet_utils_uri.cc b/icnet/utils/icnet_utils_uri.cc index 8268bdf9..53d67b29 100644 --- a/icnet/utils/icnet_utils_uri.cc +++ b/icnet/utils/icnet_utils_uri.cc @@ -16,8 +16,6 @@ #include "icnet_utils_uri.h" #include "icnet_errors_runtime_exception.h" -namespace icnet { - namespace utils { Uri::Uri() { @@ -132,6 +130,4 @@ std::string Uri::getQueryString() { return query_string_; } -} // end namespace utils - -} // end namespace icnet
\ No newline at end of file +} // end namespace utils
\ No newline at end of file diff --git a/icnet/utils/icnet_utils_uri.h b/icnet/utils/icnet_utils_uri.h index 38172282..4d422766 100644 --- a/icnet/utils/icnet_utils_uri.h +++ b/icnet/utils/icnet_utils_uri.h @@ -18,8 +18,6 @@ #include <string> #include <algorithm> // find -namespace icnet { - namespace utils { class Uri { @@ -46,6 +44,4 @@ class Uri { std::string query_string_, path_, protocol_, locator_, port_; }; // uri -} - }
\ No newline at end of file |