From bac3da61644515f05663789b122554dc77549286 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 17 Jan 2019 13:47:57 +0100 Subject: This is the first commit of the hicn project Change-Id: I6f2544ad9b9f8891c88cc4bcce3cf19bd3cc863f Signed-off-by: Luca Muscariello --- .../src/hicn/transport/http/CMakeLists.txt | 36 ++++ libtransport/src/hicn/transport/http/callbacks.h | 46 +++++ .../src/hicn/transport/http/client_connection.cc | 194 +++++++++++++++++++++ .../src/hicn/transport/http/client_connection.h | 82 +++++++++ .../src/hicn/transport/http/default_values.h | 32 ++++ libtransport/src/hicn/transport/http/facade.h | 22 +++ libtransport/src/hicn/transport/http/message.h | 58 ++++++ libtransport/src/hicn/transport/http/request.cc | 83 +++++++++ libtransport/src/hicn/transport/http/request.h | 61 +++++++ libtransport/src/hicn/transport/http/response.cc | 134 ++++++++++++++ libtransport/src/hicn/transport/http/response.h | 58 ++++++ .../src/hicn/transport/http/server_acceptor.cc | 112 ++++++++++++ .../src/hicn/transport/http/server_acceptor.h | 62 +++++++ .../src/hicn/transport/http/server_publisher.cc | 173 ++++++++++++++++++ .../src/hicn/transport/http/server_publisher.h | 72 ++++++++ 15 files changed, 1225 insertions(+) create mode 100755 libtransport/src/hicn/transport/http/CMakeLists.txt create mode 100755 libtransport/src/hicn/transport/http/callbacks.h create mode 100755 libtransport/src/hicn/transport/http/client_connection.cc create mode 100755 libtransport/src/hicn/transport/http/client_connection.h create mode 100755 libtransport/src/hicn/transport/http/default_values.h create mode 100755 libtransport/src/hicn/transport/http/facade.h create mode 100755 libtransport/src/hicn/transport/http/message.h create mode 100755 libtransport/src/hicn/transport/http/request.cc create mode 100755 libtransport/src/hicn/transport/http/request.h create mode 100755 libtransport/src/hicn/transport/http/response.cc create mode 100755 libtransport/src/hicn/transport/http/response.h create mode 100755 libtransport/src/hicn/transport/http/server_acceptor.cc create mode 100755 libtransport/src/hicn/transport/http/server_acceptor.h create mode 100755 libtransport/src/hicn/transport/http/server_publisher.cc create mode 100755 libtransport/src/hicn/transport/http/server_publisher.h (limited to 'libtransport/src/hicn/transport/http') diff --git a/libtransport/src/hicn/transport/http/CMakeLists.txt b/libtransport/src/hicn/transport/http/CMakeLists.txt new file mode 100755 index 000000000..ddcf1fdc3 --- /dev/null +++ b/libtransport/src/hicn/transport/http/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2017-2019 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. + +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/client_connection.cc + ${CMAKE_CURRENT_SOURCE_DIR}/request.cc + ${CMAKE_CURRENT_SOURCE_DIR}/server_publisher.cc + ${CMAKE_CURRENT_SOURCE_DIR}/server_acceptor.cc + ${CMAKE_CURRENT_SOURCE_DIR}/response.cc) + +list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/client_connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/request.h + ${CMAKE_CURRENT_SOURCE_DIR}/server_publisher.h + ${CMAKE_CURRENT_SOURCE_DIR}/server_acceptor.h + ${CMAKE_CURRENT_SOURCE_DIR}/default_values.h + ${CMAKE_CURRENT_SOURCE_DIR}/facade.h + ${CMAKE_CURRENT_SOURCE_DIR}/response.h + ${CMAKE_CURRENT_SOURCE_DIR}/message.h + ${CMAKE_CURRENT_SOURCE_DIR}/callbacks.h +) + +set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) +set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/callbacks.h b/libtransport/src/hicn/transport/http/callbacks.h new file mode 100755 index 000000000..5ca5fcbe2 --- /dev/null +++ b/libtransport/src/hicn/transport/http/callbacks.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017-2019 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 + +#include +#include + +namespace transport { + +namespace http { + +enum class RC : uint8_t { + SUCCESS, + CONTENT_PUBLISHED, + ERR_UNDEFINED, +}; + +using OnHttpRequest = + std::function&, const uint8_t*, + std::size_t, int request_id)>; +using DeadlineTimerCallback = std::function; +using ReceiveCallback = std::function&)>; +using OnPayloadCallback = std::function>& payload)>; +using ContentSentCallback = + std::function; + +} // namespace http + +} // namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/client_connection.cc b/libtransport/src/hicn/transport/http/client_connection.cc new file mode 100755 index 000000000..d4207bb81 --- /dev/null +++ b/libtransport/src/hicn/transport/http/client_connection.cc @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2017-2019 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 +#include + +#define DEFAULT_BETA 0.99 +#define DEFAULT_GAMMA 0.07 + +namespace transport { + +namespace http { + +using namespace transport; + +HTTPClientConnection::HTTPClientConnection() + : consumer_(TransportProtocolAlgorithms::RAAQM, io_service_), + response_(std::make_shared()), + timer_(nullptr) { + consumer_.setSocketOption( + ConsumerCallbacksOptions::CONTENT_OBJECT_TO_VERIFY, + (ConsumerContentObjectVerificationCallback)std::bind( + &HTTPClientConnection::verifyData, this, std::placeholders::_1, + std::placeholders::_2)); + + consumer_.setSocketOption( + ConsumerCallbacksOptions::CONTENT_RETRIEVED, + (ConsumerContentCallback)std::bind( + &HTTPClientConnection::processPayload, this, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3)); + + consumer_.connect(); + std::shared_ptr portal; + consumer_.getSocketOption(GeneralTransportOptions::PORTAL, portal); + timer_ = std::make_unique(portal->getIoService()); +} + +HTTPClientConnection &HTTPClientConnection::get( + const std::string &url, HTTPHeaders headers, HTTPPayload payload, + std::shared_ptr response) { + return sendRequest(url, HTTPMethod::GET, headers, payload, response); +} + +HTTPClientConnection &HTTPClientConnection::sendRequest( + const std::string &url, HTTPMethod method, HTTPHeaders headers, + HTTPPayload payload, std::shared_ptr response) { + if (!response) { + response = response_; + } + + auto start = std::chrono::steady_clock::now(); + HTTPRequest request(method, url, headers, payload); + std::string name = sendRequestGetReply(request, response); + auto end = std::chrono::steady_clock::now(); + + TRANSPORT_LOGI( + "%s %s [%s] duration: %llu [usec] %zu [bytes]\n", + method_map[method].c_str(), url.c_str(), name.c_str(), + (unsigned long long)std::chrono::duration_cast( + end - start) + .count(), + response->size()); + + return *this; +} + +std::string HTTPClientConnection::sendRequestGetReply( + const HTTPRequest &request, std::shared_ptr &response) { + const std::string &request_string = request.getRequestString(); + const std::string &locator = request.getLocator(); + + // Hash it + + uint32_t locator_hash = + utils::hash::fnv32_buf(locator.c_str(), locator.size()); + uint64_t request_hash = + utils::hash::fnv64_buf(request_string.c_str(), request_string.size()); + + consumer_.setSocketOption( + ConsumerCallbacksOptions::INTEREST_OUTPUT, + (ConsumerInterestCallback)std::bind( + &HTTPClientConnection::processLeavingInterest, this, + std::placeholders::_1, std::placeholders::_2, request_string)); + + // Send content to producer piggybacking it through first interest (to fix) + + response->clear(); + + // Factor hicn name using hash + + std::stringstream stream; + + stream << std::hex << http::default_values::ipv6_first_word << ":"; + + for (uint16_t *word = (uint16_t *)&locator_hash; + std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash)); + word++) { + stream << ":" << std::hex << *word; + } + + for (uint16_t *word = (uint16_t *)&request_hash; + std::size_t(word) < (std::size_t(&request_hash) + sizeof(request_hash)); + word++) { + stream << ":" << std::hex << *word; + } + + stream << "|0"; + + consumer_.consume(Name(stream.str()), *response); + + consumer_.stop(); + + return stream.str(); +} + +HTTPResponse &&HTTPClientConnection::response() { + // response_->parse(); + return std::move(*response_); +} + +void HTTPClientConnection::processPayload(ConsumerSocket &c, + std::size_t bytes_transferred, + const std::error_code &ec) { + if (ec) { + TRANSPORT_LOGE("Download failed!!"); + } +} + +bool HTTPClientConnection::verifyData( + ConsumerSocket &c, const core::ContentObject &contentObject) { + if (contentObject.getPayloadType() == PayloadType::CONTENT_OBJECT) { + TRANSPORT_LOGI("VERIFY CONTENT\n"); + } else if (contentObject.getPayloadType() == PayloadType::MANIFEST) { + TRANSPORT_LOGI("VERIFY MANIFEST\n"); + } + + return true; +} + +void HTTPClientConnection::processLeavingInterest( + ConsumerSocket &c, const core::Interest &interest, std::string &payload) { + // if (interest.getName().getSuffix() == 0) { + Interest &int2 = const_cast(interest); + int2.appendPayload((uint8_t *)payload.data(), payload.size()); + // } +} + +ConsumerSocket &HTTPClientConnection::getConsumer() { return consumer_; } + +HTTPClientConnection &HTTPClientConnection::stop() { + // This is thread safe and can be called from another thread + consumer_.stop(); + + return *this; +} + +HTTPClientConnection &HTTPClientConnection::setTimeout( + const std::chrono::seconds &timeout) { + timer_->cancel(); + timer_->expires_from_now(timeout); + timer_->async_wait([this](std::error_code ec) { + if (!ec) { + consumer_.stop(); + } + }); + + return *this; +} + +HTTPClientConnection &HTTPClientConnection::setCertificate( + const std::string &cert_path) { + if (consumer_.setSocketOption(GeneralTransportOptions::CERTIFICATE, + cert_path) == SOCKET_OPTION_NOT_SET) { + throw errors::RuntimeException("Error setting the certificate."); + } + + return *this; +} + +} // namespace http + +} // namespace transport diff --git a/libtransport/src/hicn/transport/http/client_connection.h b/libtransport/src/hicn/transport/http/client_connection.h new file mode 100755 index 000000000..f6e1fa03e --- /dev/null +++ b/libtransport/src/hicn/transport/http/client_connection.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2017-2019 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 +#include +#include +#include +#include +#include + +#include + +namespace transport { + +namespace http { + +using namespace interface; +using namespace core; + +class HTTPClientConnection { + public: + HTTPClientConnection(); + + HTTPClientConnection &get(const std::string &url, HTTPHeaders headers = {}, + HTTPPayload payload = {}, + std::shared_ptr response = nullptr); + + HTTPClientConnection &sendRequest( + const std::string &url, HTTPMethod method, HTTPHeaders headers = {}, + HTTPPayload payload = {}, + std::shared_ptr response = nullptr); + + HTTPResponse &&response(); + + HTTPClientConnection &stop(); + + interface::ConsumerSocket &getConsumer(); + + HTTPClientConnection &setTimeout(const std::chrono::seconds &timeout); + + HTTPClientConnection &setCertificate(const std::string &cert_path); + + private: + void processPayload(interface::ConsumerSocket &c, + std::size_t bytes_transferred, const std::error_code &ec); + + std::string sendRequestGetReply(const HTTPRequest &request, + std::shared_ptr &response); + + bool verifyData(interface::ConsumerSocket &c, + const core::ContentObject &contentObject); + + void processLeavingInterest(interface::ConsumerSocket &c, + const core::Interest &interest, + std::string &payload); + + asio::io_service io_service_; + + ConsumerSocket consumer_; + + std::shared_ptr response_; + + std::unique_ptr timer_; +}; + +} // end namespace http + +} // end namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/default_values.h b/libtransport/src/hicn/transport/http/default_values.h new file mode 100755 index 000000000..2d5a6b821 --- /dev/null +++ b/libtransport/src/hicn/transport/http/default_values.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2019 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 + +namespace transport { + +namespace http { + +namespace default_values { + +const uint16_t ipv6_first_word = 0xb001; // Network byte order + +} // namespace default_values + +} // namespace http + +} // end namespace transport diff --git a/libtransport/src/hicn/transport/http/facade.h b/libtransport/src/hicn/transport/http/facade.h new file mode 100755 index 000000000..31c2d1b8d --- /dev/null +++ b/libtransport/src/hicn/transport/http/facade.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019 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 +#include +#include + +namespace libl4 = transport; \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/message.h b/libtransport/src/hicn/transport/http/message.h new file mode 100755 index 000000000..7d4485c90 --- /dev/null +++ b/libtransport/src/hicn/transport/http/message.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2019 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 + +#include +#include +#include + +#define HTTP_VERSION "1.1" + +namespace transport { + +namespace http { + +typedef enum { GET, POST, PUT, PATCH, DELETE } HTTPMethod; + +static std::map method_map = { + {GET, "GET"}, {POST, "POST"}, {PUT, "PUT"}, + {PATCH, "PATCH"}, {DELETE, "DELETE"}, +}; + +typedef std::map HTTPHeaders; +typedef std::vector HTTPPayload; + +class HTTPMessage { + public: + virtual ~HTTPMessage() = default; + + virtual const HTTPHeaders &getHeaders() = 0; + + virtual const HTTPPayload &getPayload() = 0; + + virtual const std::string &getHttpVersion() const = 0; + + protected: + HTTPHeaders headers_; + HTTPPayload payload_; + std::string http_version_; +}; + +} // end namespace http + +} // end namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/request.cc b/libtransport/src/hicn/transport/http/request.cc new file mode 100755 index 000000000..7a63b4f75 --- /dev/null +++ b/libtransport/src/hicn/transport/http/request.cc @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2019 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 +#include + +namespace transport { + +namespace http { + +// std::map method_map + +HTTPRequest::HTTPRequest(HTTPMethod method, const std::string &url, + const HTTPHeaders &headers, + const HTTPPayload &payload) { + utils::Uri uri; + uri.parse(url); + + path_ = uri.getPath(); + query_string_ = uri.getQueryString(); + protocol_ = uri.getProtocol(); + locator_ = uri.getLocator(); + port_ = uri.getPort(); + http_version_ = HTTP_VERSION; + + headers_ = headers; + payload_ = payload; + + std::transform(locator_.begin(), locator_.end(), locator_.begin(), ::tolower); + + std::transform(protocol_.begin(), protocol_.end(), protocol_.begin(), + ::tolower); + + std::stringstream stream; + stream << method_map[method] << " " << uri.getPath() << " HTTP/" + << HTTP_VERSION << "\r\n"; + for (auto &item : headers) { + stream << item.first << ": " << item.second << "\r\n"; + } + stream << "\r\n"; + + if (payload.size() > 0) { + stream << payload.data(); + } + + request_string_ = stream.str(); +} + +const std::string &HTTPRequest::getPort() const { return port_; } + +const std::string &HTTPRequest::getLocator() const { return locator_; } + +const std::string &HTTPRequest::getProtocol() const { return protocol_; } + +const std::string &HTTPRequest::getPath() const { return path_; } + +const std::string &HTTPRequest::getQueryString() const { return query_string_; } + +const HTTPHeaders &HTTPRequest::getHeaders() { return headers_; } + +const HTTPPayload &HTTPRequest::getPayload() { return payload_; } + +const std::string &HTTPRequest::getRequestString() const { + return request_string_; +} + +const std::string &HTTPRequest::getHttpVersion() const { return http_version_; } + +} // namespace http + +} // namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/request.h b/libtransport/src/hicn/transport/http/request.h new file mode 100755 index 000000000..88d67d4ad --- /dev/null +++ b/libtransport/src/hicn/transport/http/request.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017-2019 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 +#include + +#include +#include +#include + +namespace transport { + +namespace http { + +class HTTPRequest : public HTTPMessage { + public: + HTTPRequest(HTTPMethod method, const std::string &url, + const HTTPHeaders &headers, const HTTPPayload &payload); + + const std::string &getQueryString() const; + + const std::string &getPath() const; + + const std::string &getProtocol() const; + + const std::string &getLocator() const; + + const std::string &getPort() const; + + const std::string &getRequestString() const; + + const HTTPHeaders &getHeaders() override; + + const HTTPPayload &getPayload() override; + + const std::string &getHttpVersion() const override; + + private: + std::string query_string_, path_, protocol_, locator_, port_; + std::string request_string_; + HTTPHeaders headers_; + HTTPPayload payload_; +}; + +} // end namespace http + +} // end namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/response.cc b/libtransport/src/hicn/transport/http/response.cc new file mode 100755 index 000000000..0aa9affe8 --- /dev/null +++ b/libtransport/src/hicn/transport/http/response.cc @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2017-2019 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 +#include + +#include + +#include + +namespace transport { + +namespace http { + +HTTPResponse::HTTPResponse() {} + +HTTPResponse::HTTPResponse(const HTTPHeaders &headers, + const HTTPPayload &payload) { + headers_ = headers; + payload_ = payload; +} + +const HTTPHeaders &HTTPResponse::getHeaders() { + parse(); + return headers_; +} + +const 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 *>(this)); + } + } +} + +const std::string &HTTPResponse::getStatusCode() const { return status_code_; } + +const std::string &HTTPResponse::getStatusString() const { + return status_string_; +} + +const std::string &HTTPResponse::getHttpVersion() const { + return http_version_; +} + +} // namespace http + +} // namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/response.h b/libtransport/src/hicn/transport/http/response.h new file mode 100755 index 000000000..e7dec8c40 --- /dev/null +++ b/libtransport/src/hicn/transport/http/response.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2019 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 +#include +#include + +#include +#include +#include + +namespace transport { + +namespace http { + +class HTTPResponse : public HTTPMessage, public utils::SharableVector { + public: + HTTPResponse(const HTTPHeaders &headers, const HTTPPayload &payload); + + HTTPResponse(); + + const HTTPHeaders &getHeaders() override; + + const HTTPPayload &getPayload() override; + + const std::string &getStatusCode() const; + + const std::string &getStatusString() const; + + const std::string &getHttpVersion() const override; + + void parse(); + + private: + bool parseHeaders(); + + private: + std::string status_code_; + std::string status_string_; +}; + +} // end namespace http + +} // end namespace transport \ No newline at end of file diff --git a/libtransport/src/hicn/transport/http/server_acceptor.cc b/libtransport/src/hicn/transport/http/server_acceptor.cc new file mode 100755 index 000000000..717dfb642 --- /dev/null +++ b/libtransport/src/hicn/transport/http/server_acceptor.cc @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2017-2019 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 +#include +#include + +namespace transport { + +namespace http { + +HTTPServerAcceptor::HTTPServerAcceptor(std::string &&server_locator, + OnHttpRequest callback) + : HTTPServerAcceptor(server_locator, callback) {} + +HTTPServerAcceptor::HTTPServerAcceptor(std::string &server_locator, + OnHttpRequest callback) + : callback_(callback) { + utils::Uri uri; + + uri.parseProtocolAndLocator(server_locator); + std::string protocol = uri.getProtocol(); + std::string locator = uri.getLocator(); + + std::transform(locator.begin(), locator.end(), locator.begin(), ::tolower); + + std::transform(protocol.begin(), protocol.end(), protocol.begin(), ::tolower); + + if (protocol != "http") { + throw errors::RuntimeException( + "Malformed server_locator. The locator format should be in the form " + "http://locator"); + } + + uint32_t locator_hash = + utils::hash::fnv32_buf(locator.c_str(), locator.size()); + + std::stringstream stream; + stream << std::hex << http::default_values::ipv6_first_word << ":0000"; + + for (uint16_t *word = (uint16_t *)&locator_hash; + std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash)); + word++) { + stream << ":" << std::hex << *word; + } + + stream << "::0"; + + std::string network = stream.str(); + + core::Prefix acceptor_namespace(network, 64); + + std::string producer_identity = "acceptor_producer"; + acceptor_producer_ = std::make_shared( + io_service_); /*, + utils::Identity::generateIdentity(producer_identity));*/ + acceptor_producer_->registerPrefix(acceptor_namespace); +} + +void HTTPServerAcceptor::listen(bool async) { + acceptor_producer_->setSocketOption( + ProducerCallbacksOptions::INTEREST_INPUT, + (ProducerInterestCallback)bind( + &HTTPServerAcceptor::processIncomingInterest, this, + std::placeholders::_1, std::placeholders::_2)); + acceptor_producer_->connect(); + + if (!async) { + acceptor_producer_->serveForever(); + } +} + +void HTTPServerAcceptor::processIncomingInterest(ProducerSocket &p, + const Interest &interest) { + // Temporary solution. With + utils::Array payload = interest.getPayload(); + + int request_id = utils::hash::fnv32_buf(payload.data(), payload.length()); + + if (publishers_.find(request_id) != publishers_.end()) { + if (publishers_[request_id]) { + publishers_[request_id]->getProducer().onInterest(interest); + return; + } + } + + publishers_[request_id] = + std::make_shared(interest.getName()); + callback_(publishers_[request_id], (uint8_t *)payload.data(), + payload.length(), request_id); +} + +std::map> + &HTTPServerAcceptor::getPublishers() { + return publishers_; +} + +} // namespace http + +} // namespace transport diff --git a/libtransport/src/hicn/transport/http/server_acceptor.h b/libtransport/src/hicn/transport/http/server_acceptor.h new file mode 100755 index 000000000..549962414 --- /dev/null +++ b/libtransport/src/hicn/transport/http/server_acceptor.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2019 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 +#include +#include +#include +#include +#include + +#include +#include + +namespace transport { + +namespace http { + +class HTTPServerAcceptor { + friend class HTTPServerPublisher; + + public: + HTTPServerAcceptor(std::string &&server_locator, OnHttpRequest callback); + HTTPServerAcceptor(std::string &server_locator, OnHttpRequest callback); + + void listen(bool async); + + std::map> &getPublishers(); + + // void asyncSendResponse(); + + // HTTPClientConnection& get(std::string &url, HTTPHeaders headers = {}, + // HTTPPayload payload = {}); + // + // HTTPResponse&& response(); + + private: + void processIncomingInterest(ProducerSocket &p, const Interest &interest); + + OnHttpRequest callback_; + asio::io_service io_service_; + std::shared_ptr acceptor_producer_; + + std::map> publishers_; +}; + +} // end namespace http + +} // end namespace transport diff --git a/libtransport/src/hicn/transport/http/server_publisher.cc b/libtransport/src/hicn/transport/http/server_publisher.cc new file mode 100755 index 000000000..012f36091 --- /dev/null +++ b/libtransport/src/hicn/transport/http/server_publisher.cc @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2017-2019 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 +#include + +namespace transport { + +namespace http { + +HTTPServerPublisher::HTTPServerPublisher(const core::Name &content_name) + : content_name_(content_name, true) { + std::string identity = "acceptor_producer"; + producer_ = std::make_unique(io_service_); + // utils::Identity::generateIdentity(identity)); + core::Prefix publisher_prefix(content_name_, 128); + producer_->registerPrefix(publisher_prefix); +} + +HTTPServerPublisher::~HTTPServerPublisher() { + if (timer_) { + this->timer_->cancel(); + } +} + +HTTPServerPublisher &HTTPServerPublisher::attachPublisher() { + // Create a new publisher + producer_->setSocketOption(GeneralTransportOptions::DATA_PACKET_SIZE, + 1410_U32); + producer_->connect(); + return *this; +} + +HTTPServerPublisher &HTTPServerPublisher::setTimeout( + const std::chrono::milliseconds &timeout, bool timeout_renewal) { + std::shared_ptr portal; + producer_->getSocketOption(GeneralTransportOptions::PORTAL, portal); + timer_ = + std::make_unique(portal->getIoService(), timeout); + + wait_callback_ = [this](const std::error_code &e) { + if (!e) { + producer_->stop(); + } + }; + + if (timeout_renewal) { + interest_enter_callback_ = [this, timeout](ProducerSocket &p, + const Interest &interest) { + this->timer_->cancel(); + this->timer_->expires_from_now(timeout); + this->timer_->async_wait(wait_callback_); + }; + + producer_->setSocketOption( + ProducerCallbacksOptions::CACHE_HIT, + (ProducerInterestCallback)interest_enter_callback_); + } + + timer_->async_wait(wait_callback_); + + return *this; +} + +void HTTPServerPublisher::publishContent( + const uint8_t *buf, size_t buffer_size, + std::chrono::milliseconds content_lifetime, bool is_last) { + if (producer_) { + producer_->setSocketOption( + GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME, + static_cast(content_lifetime.count())); + producer_->produce(content_name_, buf, buffer_size, is_last); + // producer_->setSocketOption(ProducerCallbacksOptions::CACHE_MISS, + // [this](ProducerSocket &p, const + // core::Interest &interest){ + // producer_->stop(); + // }); + } +} + +template +void HTTPServerPublisher::asyncPublishContent( + const uint8_t *buf, size_t buffer_size, + std::chrono::milliseconds content_lifetime, Handler &&handler, + bool is_last) { + if (producer_) { + producer_->setSocketOption( + GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME, + static_cast(content_lifetime.count())); + producer_->asyncProduce(content_name_, buf, buffer_size, + std::forward(handler), is_last); + } +} + +void HTTPServerPublisher::serveClients() { producer_->serveForever(); } + +void HTTPServerPublisher::stop() { + std::shared_ptr portal_ptr; + producer_->getSocketOption(GeneralTransportOptions::PORTAL, portal_ptr); + portal_ptr->getIoService().stop(); +} + +ProducerSocket &HTTPServerPublisher::getProducer() { return *producer_; } + +void HTTPServerPublisher::setPublisherName(std::string &name, + std::string &mask) { + // Name represents the last 64 bits of the ipv6 address. + // It is an ipv6 address with the first 64 bits set to 0 + uint16_t i; + std::string s = content_name_.toString(); + std::shared_ptr sockaddr = content_name_.getAddress(); + in6_addr name_ipv6 = ((core::Sockaddr6 *)sockaddr.get())->sin6_addr; + + in6_addr bitmask, new_address, _name; + + if (inet_pton(AF_INET6, mask.c_str(), &bitmask) != 1) { + throw errors::RuntimeException("Error during conversion to ipv6 address."); + } + + if (inet_pton(AF_INET6, name.c_str(), &_name) != 1) { + throw errors::RuntimeException("Error during conversion to ipv6 address."); + } + + for (i = 0; i < sizeof(new_address.s6_addr); i++) { + new_address.s6_addr[i] = name_ipv6.s6_addr[i] & bitmask.s6_addr[i]; + } + + for (i = 0; i < sizeof(new_address.s6_addr); i++) { + new_address.s6_addr[i] |= _name.s6_addr[i] & ~bitmask.s6_addr[i]; + } + + // Effectively change the name + char str[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &new_address, str, INET6_ADDRSTRLEN); + std::string str2(str); + + core::Name new_name(str2, 0); + + // If the new name differs from the one required by the consumer part, send a + // manifest + if (!new_name.equals(content_name_, false)) { + // Publish manifest pointing to the new name + + auto manifest = + std::make_shared(content_name_.setSuffix(0)); + + content_name_ = core::Name(str2, 0); + + // manifest->setNameList(content_name_); + manifest->setLifetime(4000 * 1000); + manifest->encode(); + producer_->produce(*manifest); + + core::Prefix ns(content_name_, 128); + producer_->registerPrefix(ns); + } +} + +} // namespace http + +} // namespace transport diff --git a/libtransport/src/hicn/transport/http/server_publisher.h b/libtransport/src/hicn/transport/http/server_publisher.h new file mode 100755 index 000000000..91f7e43e9 --- /dev/null +++ b/libtransport/src/hicn/transport/http/server_publisher.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2019 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 +#include +#include + +#include +#include + +namespace transport { + +namespace http { + +using namespace interface; +using namespace core; + +class HTTPServerPublisher { + public: + HTTPServerPublisher(const core::Name &content_name); + + ~HTTPServerPublisher(); + + void publishContent(const uint8_t *buf, size_t buffer_size, + std::chrono::milliseconds content_lifetime, bool is_last); + + template + void asyncPublishContent(const uint8_t *buf, size_t buffer_size, + std::chrono::milliseconds content_lifetime, + Handler &&handler, bool is_last); + + void serveClients(); + + void stop(); + + ProducerSocket &getProducer(); + + HTTPServerPublisher &setTimeout(const std::chrono::milliseconds &timeout, + bool timeout_renewal); + + HTTPServerPublisher &attachPublisher(); + + void setPublisherName(std::string &name, std::string &mask); + + private: + Name content_name_; + std::unique_ptr timer_; + asio::io_service io_service_; + std::unique_ptr producer_; + ProducerInterestCallback interest_enter_callback_; + utils::UserCallback wait_callback_; + + utils::SharableVector receive_buffer_; +}; + +} // end namespace http + +} // end namespace transport -- cgit 1.2.3-korg