From a81921f0fd4296f8def24665174062782b3480be Mon Sep 17 00:00:00 2001 From: Mauro Sardara Date: Fri, 16 Feb 2018 17:53:36 +0100 Subject: Added reverse proxy (TCP --> ICN) functionality Change-Id: I2305aa11aea4a37d3d63c6399c49389f78dfd91c Signed-off-by: Mauro Sardara --- CMakeLists.txt | 101 ++++++++++++++++++++++++-------------- cmake/Modules/FindLibhicnet.cmake | 39 --------------- config.h.in | 3 +- dockerfile.ubuntu.xenial | 4 +- http-client/http_client.h | 24 ++++----- http-client/http_client_icn.cc | 41 ++++++++++++++++ http-client/http_client_icn.h | 34 +++++++++++++ http-client/http_client_tcp.cc | 99 +++++++++++++++++++++++++++++++++++++ http-client/http_client_tcp.h | 35 +++++++++++++ http-server/common.h | 16 ++---- http-server/configuration.h | 5 +- http-server/content.h | 5 +- http-server/http_server.cc | 56 ++++++++++----------- http-server/http_server.h | 12 ++--- http-server/icn_request.h | 9 ++-- http-server/icn_response.cc | 10 ++-- http-server/icn_response.h | 11 ++--- http-server/request.h | 7 ++- http-server/response.cc | 1 + http-server/response.h | 13 ++--- http-server/socket_request.h | 5 +- http-server/socket_response.h | 5 +- main.cc | 98 ++++++++++++++++++++++++------------ scripts/build-package.sh | 8 --- 24 files changed, 414 insertions(+), 227 deletions(-) delete mode 100644 cmake/Modules/FindLibhicnet.cmake create mode 100644 http-client/http_client_icn.cc create mode 100644 http-client/http_client_icn.h create mode 100644 http-client/http_client_tcp.cc create mode 100644 http-client/http_client_tcp.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b51e1b3..674f0386 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,66 +23,93 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") option(ICNET "Link against Libicnet." ON) -option(HICNET "Link against Libhicnet." OFF) -if (HICNET) - find_package(Libhicnet REQUIRED) - set(TRANSPORT_LIBRARY HICNET) - set(ICNET OFF) - set(PREFIX "hicn-") -else() - find_package(Libicnet REQUIRED) - set(TRANSPORT_LIBRARY ICNET) - set(PREFIX "") -endif() +find_package(Libicnet REQUIRED) +set(TRANSPORT_LIBRARY ICNET) +set(PREFIX "") configure_file("${PROJECT_SOURCE_DIR}/config.h.in" "${CMAKE_BINARY_DIR}/config.h") -include_directories(${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIRS} http-server http-client) - -find_package(Threads REQUIRED) - -find_package(CURL REQUIRED) -include_directories(${CURL_INCLUDE_DIRS}) +include_directories(${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIRS}) + +if(ANDROID_API) + find_package(Threads REQUIRED) + set(CURL_INCLUDE_DIRS "$ENV{DISTILLERY_ROOT_DIR}/external/libcurl_android/jni/libcurl/include") + set(CURL_LIBRARIES "$ENV{DISTILLERY_ROOT_DIR}/usr/lib/libcurl.a" "$ENV{DISTILLERY_ROOT_DIR}/usr/lib/libcurl-library.a") + find_package(Boost 1.53.0 COMPONENTS regex system filesystem REQUIRED) + include_directories(SYSTEM ${Boost_INCLUDE_DIR} ${CMAKE_BINARY_DIR} ${CURL_INCLUDE_DIRS} ${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIR} http-server http-client) + include_directories(${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.9/include) + include_directories(${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include) + set(ANDROID_LIBRARIES "${ANDROID_NDK}/platforms/android-24/arch-arm/usr/lib/libz.a" "${ANDROID_NDK}/platforms/android-24/arch-arm/usr/lib/liblog.so" "$ENV{NDK}/sources/cxx-stl/gnu-libstdc++/4.9/libs/$ENV{ABI}/libgnustl_shared.so") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} ${ANDROID_C_FLAGS} -Wall") +else() + find_package(Threads REQUIRED) -find_package(Boost 1.53.0 COMPONENTS regex system filesystem REQUIRED) -include_directories(SYSTEM ${Boost_INCLUDE_DIR} ${CMAKE_BINARY_DIR} ${CURL_INCLUDE_DIRS} ${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIR}) + find_package(CURL REQUIRED) + include_directories(${CURL_INCLUDE_DIRS}) -set(SOURCE_FILES - main.cc + find_package(Boost 1.53.0 COMPONENTS regex system filesystem REQUIRED) + include_directories(SYSTEM ${Boost_INCLUDE_DIR} ${CMAKE_BINARY_DIR} ${CURL_INCLUDE_DIRS} ${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIR} http-server http-client) +endif() +set(LIB_SOURCE_FILES http-server/http_server.cc - http-server/http_server.h http-server/response.cc - http-server/response.h - http-server/common.h http-server/socket_response.cc - http-server/socket_response.h http-server/icn_response.cc - http-server/icn_response.h http-server/content.cc - http-server/content.h http-server/request.cc - http-server/request.h http-server/icn_request.cc - http-server/icn_request.h http-server/socket_request.cc - http-server/socket_request.h http-server/configuration.cc + http-client/http_client_tcp.cc + http-client/http_client_icn.cc) + +set(LIB_SERVER_HEADER_FILES + http-server/http_server.h + http-server/response.h + http-server/common.h + http-server/socket_response.h + http-server/content.h + http-server/request.h + http-server/icn_request.h + http-server/socket_request.h http-server/configuration.h - http-client/http_client.cc - http-client/http_client.h - ${CMAKE_BINARY_DIR}/config.h) + ${CMAKE_BINARY_DIR}/config.h + http-server/icn_response.h) + +set(LIB_CLIENT_HEADER_FILES + http-client/http_client_tcp.h + http-client/http_client_icn.h + http-client/http_client.h) + +set(APP_SOURCE_FILES + main.cc) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS} -fpermissive") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS} -fpermissive") set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS} -fpermissive") -add_executable(${PREFIX}http-server ${SOURCE_FILES}) -target_link_libraries(${PREFIX}http-server ${LIB${TRANSPORT_LIBRARY}_LIBRARY} ${CURL_LIBRARY} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +add_library(${PREFIX}httpserver ${LIB_SOURCE_FILES}) + +if(ANDROID_API) + target_link_libraries(${PREFIX}httpserver ${LIB${TRANSPORT_LIBRARY}_LIBRARY} ${CURL_LIBRARY} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${ANDROID_LIBRARIES} ) + target_compile_definitions(${PREFIX}httpserver PRIVATE ${TRANSPORT_LIBRARY}=1) +else() + + target_link_libraries(${PREFIX}httpserver ${LIB${TRANSPORT_LIBRARY}_LIBRARY} ${CURL_LIBRARY} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + + add_executable(${PREFIX}http-server ${APP_SOURCE_FILES}) + target_link_libraries(${PREFIX}http-server ${PREFIX}httpserver) + install(TARGETS ${PREFIX}http-server DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) +endif() + +install(TARGETS ${PREFIX}httpserver DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) + +install(FILES ${LIB_SERVER_HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/http-server) +install(FILES ${LIB_CLIENT_HEADER_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/http-client) -install(TARGETS ${PREFIX}http-server DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) # Generate DEB / RPM packages @@ -104,7 +131,7 @@ set(CPACK_PACKAGE_CONTACT ${CONTACT}) # Get the version execute_process(COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/version OUTPUT_VARIABLE PACKAGE_VERSION) -string(STRIP ${PACKAGE_VERSION} PACKAGE_VERSION) +string(STRIP "${PACKAGE_VERSION}" PACKAGE_VERSION) string(TOLOWER ${TRANSPORT_LIBRARY} TRANSPORT_DEPENDENCY) diff --git a/cmake/Modules/FindLibhicnet.cmake b/cmake/Modules/FindLibhicnet.cmake deleted file mode 100644 index 0d4f5fbc..00000000 --- a/cmake/Modules/FindLibhicnet.cmake +++ /dev/null @@ -1,39 +0,0 @@ -######################################## -# -# Find the Libhicnet libraries and includes -# This module sets: -# LIBHICNET_FOUND: True if Libconsumer-producer was found -# LIBHICNETR_LIBRARY: The Libconsumer-producer library -# LIBHICNET_LIBRARIES: The Libconsumer-producer library and dependencies -# LIBHICNET_INCLUDE_DIR: The Libconsumer-producer include dir -# - -set(LIBHICNET_SEARCH_PATH_LIST - ${LIBHICNET_HOME} - $ENV{LIBHICNETHOME} - $ENV{CCNX_HOME} - $ENV{PARC_HOME} - $ENV{FOUNDATION_HOME} - /usr/local/parc - /usr/local/ccnx - /usr/local/ccn - /usr/local - /opt - /usr - ) - -find_path(LIBHICNET_INCLUDE_DIR hicnet/hicnet_core_common.h - HINTS ${LIBHICNET_SEARCH_PATH_LIST} - PATH_SUFFIXES include - DOC "Find the libhicnet includes") - -find_library(LIBHICNET_LIBRARY NAMES hicnet - HINTS ${LIBHICNET_SEARCH_PATH_LIST} - PATH_SUFFIXES lib - DOC "Find the libhicnet libraries") - -set(LIBHICNET_LIBRARIES ${LIBHICNET_LIBRARY}) -set(LIBHICNET_INCLUDE_DIRS ${LIBHICNET_INCLUDE_DIR}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Libhicnet DEFAULT_MSG LIBHICNET_LIBRARY LIBHICNET_INCLUDE_DIR) diff --git a/config.h.in b/config.h.in index d10e62ee..ac3f5f2d 100644 --- a/config.h.in +++ b/config.h.in @@ -15,5 +15,4 @@ #pragma once -#cmakedefine ICNET -#cmakedefine HICNET +#cmakedefine ICNET \ No newline at end of file diff --git a/dockerfile.ubuntu.xenial b/dockerfile.ubuntu.xenial index 42f141c5..362eff41 100644 --- a/dockerfile.ubuntu.xenial +++ b/dockerfile.ubuntu.xenial @@ -11,12 +11,12 @@ RUN \ sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \ apt-get update && \ apt-get -y upgrade && \ - apt-get install -y git build-essential curl software-properties-common apt-transport-https nano && \ + apt-get install -y git build-essential curl software-properties-common apt-transport-https git-core && \ echo "deb [trusted=yes] http://nexus.fd.io/content/repositories/fd.io.master.ubuntu.xenial.main ./" | tee /etc/apt/sources.list.d/99fd.io.master.list && \ sh -c "echo 'deb http://archive.getdeb.net/ubuntu xenial-getdeb apps' >> /etc/apt/sources.list.d/getdeb.list" && \ echo "deb [trusted=yes] https://engci-maven-master.cisco.com/artifactory/icn-debian xenial main" | tee /etc/apt/sources.list.d/artifactory.icndebian.list && \ apt-get update && \ - apt-get install -y git-core build-essential \ + apt-get install -y git-core build-essential nano \ libhicnet-dev libhicn-dev libcurl4-openssl-dev \ libboost-system-dev libboost-regex-dev libboost-filesystem-dev && \ rm -rf /var/lib/apt/lists/* diff --git a/http-client/http_client.h b/http-client/http_client.h index 19d3c41e..9bd998bd 100644 --- a/http-client/http_client.h +++ b/http-client/http_client.h @@ -13,23 +13,19 @@ * limitations under the License. */ -#ifndef HTTP_CLIENT_H_ -#define HTTP_CLIENT_H_ +#pragma once + +#include "config.h" #include +# include + class HTTPClient { public: - HTTPClient(); - ~HTTPClient(); - /** - * Download a file using HTTP GET and store in in a std::string - * @param url The URL to download - * @return The download result - */ - bool download(const std::string& url, std::ostream& out); - private: - void* curl_; -}; + virtual ~HTTPClient() = default; -#endif // HTTP_CLIENT_H_ \ No newline at end of file + virtual void setTcp() = 0; + + virtual bool download(const std::string &url, std::ostream &out) = 0; +}; diff --git a/http-client/http_client_icn.cc b/http-client/http_client_icn.cc new file mode 100644 index 00000000..88294f80 --- /dev/null +++ b/http-client/http_client_icn.cc @@ -0,0 +1,41 @@ +/* + * 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 "http_client_icn.h" +#include "response.h" + +#include + +using namespace std; + +HTTPClientIcn::HTTPClientIcn(uint32_t timeout) { + std::chrono::seconds _timeout(timeout); + connection_.setTimeout(_timeout); +} + +void HTTPClientIcn::setTcp() { + +} + +HTTPClientIcn::~HTTPClientIcn() { + +} + +bool HTTPClientIcn::download(const std::string& url, std::ostream& out) { + connection_.get(url); + libl4::http::HTTPResponse r = connection_.response(); + out.write(reinterpret_cast(r.data()), r.size()); + return true; +} diff --git a/http-client/http_client_icn.h b/http-client/http_client_icn.h new file mode 100644 index 00000000..67cc499c --- /dev/null +++ b/http-client/http_client_icn.h @@ -0,0 +1,34 @@ +/* + * 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 "http_client.h" + +#include + +class HTTPClientIcn : public HTTPClient { + public: + HTTPClientIcn(uint32_t timeout); + + void setTcp(); + + ~HTTPClientIcn(); + + bool download(const std::string &url, std::ostream &out); + private: + libl4::http::HTTPClientConnection connection_; + +}; diff --git a/http-client/http_client_tcp.cc b/http-client/http_client_tcp.cc new file mode 100644 index 00000000..ec83cd66 --- /dev/null +++ b/http-client/http_client_tcp.cc @@ -0,0 +1,99 @@ +/* + * 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 "http_client_tcp.h" +#include "response.h" + +#include +#include +#include +#include +#include + +using namespace std; + +struct UserData { + void * out; + void * curl; + bool tcp; + bool first_time; +}; + +typedef struct UserData UserData; + +size_t write_data(void *ptr, size_t size, size_t nmemb, void *user_data) { + + UserData *data = (UserData *) user_data; + + if(data->tcp && data->first_time) { + double cl; + + int res = curl_easy_getinfo(data->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl); + + if(res >= 0){ + *(ostream *)data->out << "HTTP/1.0 200 OK\r\nContent-Length: " << std::size_t(cl) << "\r\n\r\n"; + } + + data->first_time = false; + } + + ((icn_httpserver::Response*) data->out)->write((const char*)ptr, size * nmemb); +// ((icn_httpserver::Response*) data->out)->send(); + return size * nmemb; +} + +HTTPClientTcp::HTTPClientTcp() { + tcp_ = false; + first_time = true; + curl_ = curl_easy_init(); +} + +void HTTPClientTcp::setTcp() { + tcp_ = true; +} + +HTTPClientTcp::~HTTPClientTcp() { + curl_easy_cleanup(curl_); +} + +bool HTTPClientTcp::download(const std::string& url, std::ostream& out) { + curl_easy_setopt(curl_, CURLOPT_URL, url.c_str()); + + /* example.com is redirected, so we tell libcurl to follow redirection */ + curl_easy_setopt(curl_, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "deflate"); + + curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, write_data); + UserData data; + data.out = &out; + data.curl = curl_; + data.tcp = tcp_; + data.first_time = first_time; + + curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &data); + + /* Perform the request, res will get the return code */ + CURLcode res = curl_easy_perform(curl_); + + /* Check for errors */ + if (res != CURLE_OK) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + return false; + } + + return true; +} diff --git a/http-client/http_client_tcp.h b/http-client/http_client_tcp.h new file mode 100644 index 00000000..b8324717 --- /dev/null +++ b/http-client/http_client_tcp.h @@ -0,0 +1,35 @@ +/* + * 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 "http_client.h" + +#include + +class HTTPClientTcp : public HTTPClient { + public: + HTTPClientTcp(); + + void setTcp(); + + ~HTTPClientTcp(); + + bool download(const std::string& url, std::ostream& out); + private: + bool first_time; + bool tcp_; + void* curl_; +}; diff --git a/http-server/common.h b/http-server/common.h index 580f8a41..3d88fc42 100644 --- a/http-server/common.h +++ b/http-server/common.h @@ -13,20 +13,12 @@ * limitations under the License. */ -#ifndef ICN_WEB_SERVER_COMMON_H_ -#define ICN_WEB_SERVER_COMMON_H_ +#pragma once #include "config.h" -#if defined(HICNET) - #include - #include -#elif defined(ICNET) - #include - #include -#else - #error "No ICN tranport library to which link against." -#endif +#include +#include #include #include @@ -45,5 +37,3 @@ typedef boost::asio::ip::tcp::socket socket_type; typedef std::function SendCallback; - -#endif // ICN_WEB_SERVER_COMMON_H_ diff --git a/http-server/configuration.h b/http-server/configuration.h index 65d3170a..8939fb75 100644 --- a/http-server/configuration.h +++ b/http-server/configuration.h @@ -13,8 +13,7 @@ * limitations under the License. */ -#ifndef ICN_WEB_SERVER_CONFIGURATION_H_ -#define ICN_WEB_SERVER_CONFIGURATION_H_ +#pragma once #include "common.h" @@ -48,5 +47,3 @@ class Configuration { }; } // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_CONFIGURATION_H_ diff --git a/http-server/content.h b/http-server/content.h index a81ad643..4e2fe74f 100644 --- a/http-server/content.h +++ b/http-server/content.h @@ -15,8 +15,7 @@ #include "common.h" -#ifndef ICN_WEB_SERVER_CONTENT_H_ -#define ICN_WEB_SERVER_CONTENT_H_ +#pragma once namespace icn_httpserver { @@ -34,5 +33,3 @@ class Content }; } // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_CONTENT_H_ diff --git a/http-server/http_server.cc b/http-server/http_server.cc index 478d072e..a0ec905f 100644 --- a/http-server/http_server.cc +++ b/http-server/http_server.cc @@ -23,11 +23,13 @@ */ #include "http_server.h" - namespace icn_httpserver { HttpServer::HttpServer(unsigned short port, - std::string icn_name, size_t num_threads, long timeout_request, long timeout_send_or_receive) + std::string icn_name, + size_t num_threads, + long timeout_request, + long timeout_send_or_receive) : config_(port, num_threads), icn_name_(icn_name), internal_io_service_(std::make_shared()), @@ -53,7 +55,8 @@ HttpServer::HttpServer(unsigned short port, void HttpServer::onIcnRequest(std::shared_ptr &publisher, const uint8_t *buffer, - std::size_t size) { + std::size_t size, + int request_id) { std::shared_ptr request = std::make_shared(publisher); request->getContent().rdbuf()->sputn((char*)buffer, size); @@ -61,29 +64,21 @@ void HttpServer::onIcnRequest(std::shared_ptr return; } - int request_id = libl4::utils::Hash::hash32(buffer, size); - - std::cout << "Request ID" << request_id << std::endl; + std::map>& icn_publishers = icn_acceptor_->getPublishers(); std::unique_lock lock(thread_list_mtx_); - if (icn_publishers_.size() < config_.getNum_threads()) { - if (icn_publishers_.find(request_id) == icn_publishers_.end()) { + if (icn_publishers.size() < config_.getNum_threads()) { std::cout << "Received request for: " << request->getPath() << std::endl; - icn_publishers_[request_id] = publisher; - icn_publishers_[request_id]->attachPublisher(); - if (request->getPath().substr(request->getPath().find_last_of(".") + 1) == "mpd") { - icn_publishers_[request_id]->setTimeout(1); - } else { - icn_publishers_[request_id]->setTimeout(5); - } + + publisher->attachPublisher(); std::cout << "Starting new thread" << std::endl; io_service_.dispatch([this, request, request_id]() { + std::map>& icn_publishers = icn_acceptor_->getPublishers(); find_resource(nullptr, request); - icn_publishers_[request_id]->serveClients(); + icn_publishers[request_id]->serveClients(); std::unique_lock lock(thread_list_mtx_); - icn_publishers_.erase(request_id); + icn_publishers.erase(request_id); }); - } } } @@ -92,7 +87,8 @@ void HttpServer::setIcnAcceptor() { this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); + std::placeholders::_3, + std::placeholders::_4)); icn_acceptor_->listen(true); } @@ -117,6 +113,7 @@ void HttpServer::spawnThreads() { accept(); + //If num_threads>1, start m_io_service.run() in (num_threads-1) threads for thread-pooling socket_threads_.clear(); for (size_t c = 1; c < config_.getNum_threads(); c++) { @@ -124,6 +121,7 @@ void HttpServer::spawnThreads() { io_service_.run(); }); } + } void HttpServer::start() { @@ -148,13 +146,13 @@ void HttpServer::start() { } spawnThreads(); + setIcnAcceptor(); // Wait for the rest of the threads, if any, to finish as well for (auto &t: socket_threads_) { t.join(); } - // for (auto &t : icn_threads) { // t.second.get(); // } @@ -162,17 +160,14 @@ void HttpServer::start() { void HttpServer::stop() { acceptor_.close(); - icn_acceptor_.reset(); + io_service_.stop(); - for (auto &p: icn_publishers_) { - p.second->stop(); - } + std::map>& icn_publishers = icn_acceptor_->getPublishers(); - for (auto p : icn_publishers_) { - p.second.reset(); + for (auto &p : icn_publishers) { + p.second->stop(); } - } void HttpServer::accept() { @@ -251,7 +246,7 @@ void HttpServer::read_request_and_content(std::shared_ptr socket) { } unsigned long long content_length; try { - content_length = stoull(it->second); + content_length = atol(it->second.c_str()); } catch (const std::exception &) { return; } @@ -385,7 +380,7 @@ void HttpServer::write_response(std::shared_ptr socket, float http_version; try { - http_version = stof(request->getHttp_version()); + http_version = atof(request->getHttp_version().c_str()); } catch (const std::exception &) { return; } @@ -403,12 +398,15 @@ void HttpServer::write_response(std::shared_ptr socket, }); }); + try { resource_function(response, request); } catch (const std::exception &) { return; } + } } // end namespace icn_httpserver + diff --git a/http-server/http_server.h b/http-server/http_server.h index 704863d5..630f26b6 100644 --- a/http-server/http_server.h +++ b/http-server/http_server.h @@ -22,8 +22,7 @@ * SOFTWARE. */ -#ifndef ICN_WEB_SERVER_WEB_SERVER_H_ -#define ICN_WEB_SERVER_WEB_SERVER_H_ +#pragma once #include "common.h" #include "icn_request.h" @@ -49,6 +48,7 @@ namespace icn_httpserver { class HttpServer { public: + explicit HttpServer(unsigned short port, std::string icn_name, size_t num_threads, @@ -71,10 +71,11 @@ class HttpServer { void send(std::shared_ptr response, SendCallback callback = nullptr) const; std::unordered_map > resource; + std::unordered_map default_resource; + void onIcnRequest(std::shared_ptr& publisher, const uint8_t* buffer, std::size_t size, int request_id); private: - void onIcnRequest(std::shared_ptr& publisher, const uint8_t* buffer, std::size_t size); void spawnThreads(); @@ -100,11 +101,8 @@ class HttpServer { boost::asio::io_service &io_service_; boost::asio::ip::tcp::acceptor acceptor_; std::vector socket_threads_; - - // ICN parameters std::string icn_name_; std::shared_ptr icn_acceptor_; - std::unordered_map> icn_publishers_; std::mutex thread_list_mtx_; long timeout_request_; @@ -113,5 +111,3 @@ class HttpServer { }; } // end namespace icn_httpserver - -#endif //ICN_WEB_SERVER_WEB_SERVER_H_ diff --git a/http-server/icn_request.h b/http-server/icn_request.h index ec9ee198..d18a6e64 100644 --- a/http-server/icn_request.h +++ b/http-server/icn_request.h @@ -13,8 +13,7 @@ * limitations under the License. */ -#ifndef ICN_WEB_SERVER_ICNREQUEST_H_ -#define ICN_WEB_SERVER_ICNREQUEST_H_ +#pragma once #include "common.h" #include "request.h" @@ -32,6 +31,8 @@ class IcnRequest std::string method, std::string http_version); + ~IcnRequest() = default; + const std::string &getName() const; void setName(const std::string &name); @@ -51,6 +52,4 @@ class IcnRequest }; -} // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_ICNREQUEST_H_ +} // end namespace icn_httpserver \ No newline at end of file diff --git a/http-server/icn_response.cc b/http-server/icn_response.cc index 9741556b..630ee001 100644 --- a/http-server/icn_response.cc +++ b/http-server/icn_response.cc @@ -25,14 +25,13 @@ IcnResponse::IcnResponse(std::shared_ptr publi } void IcnResponse::send(const SendCallback &callback) { + std::size_t buffer_size = this->streambuf_.size(); this->streambuf_.commit(this->streambuf_.size()); - std::cout << "Rrsponse Id " << response_id_ << std::endl; - this->publisher_->publishContent(boost::asio::buffer_cast(this->streambuf_.data()), buffer_size, - this->response_lifetime_, + std::chrono::milliseconds(100000), this->response_id_, this->is_last_); @@ -43,4 +42,9 @@ void IcnResponse::send(const SendCallback &callback) { } } +void IcnResponse::setResponseLifetime(const std::chrono::milliseconds &response_lifetime) { + this->publisher_->setTimeout(response_lifetime, true); + Response::setResponseLifetime(response_lifetime); +} + } // end namespace icn_httpserver diff --git a/http-server/icn_response.h b/http-server/icn_response.h index 13a75629..7019590b 100644 --- a/http-server/icn_response.h +++ b/http-server/icn_response.h @@ -13,10 +13,9 @@ * limitations under the License. */ -#include "response.h" +#pragma once -#ifndef ICN_WEB_SERVER_ICNRESPONSE_H_ -#define ICN_WEB_SERVER_ICNRESPONSE_H_ +#include "response.h" namespace icn_httpserver { @@ -30,7 +29,9 @@ class IcnResponse std::string ndn_path, int response_id); - void send(const SendCallback &callback = nullptr); + void send(const SendCallback &callback = nullptr) override; + + void setResponseLifetime(const std::chrono::milliseconds &response_lifetime) override; private: std::string ndn_name_; @@ -40,5 +41,3 @@ class IcnResponse }; } // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_ICNRESPONSE_H_ diff --git a/http-server/request.h b/http-server/request.h index 6ffff296..3f61a46b 100644 --- a/http-server/request.h +++ b/http-server/request.h @@ -13,8 +13,7 @@ * limitations under the License. */ -#ifndef ICN_WEB_SERVER_REQUEST_H_ -#define ICN_WEB_SERVER_REQUEST_H_ +#pragma once #include "common.h" #include "content.h" @@ -46,6 +45,8 @@ class Request { virtual void read_remote_endpoint_data(socket_type &socket) { }; + virtual ~Request() = default; + const std::string &getMethod() const; void setMethod(const std::string &method); @@ -79,5 +80,3 @@ class Request { }; } // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_REQUEST_H_ diff --git a/http-server/response.cc b/http-server/response.cc index 21a93dd8..c4560ba9 100644 --- a/http-server/response.cc +++ b/http-server/response.cc @@ -45,6 +45,7 @@ void Response::setIsLast(bool is_last) { const std::chrono::milliseconds &Response::getResponseLifetime() const { return response_lifetime_; } + void Response::setResponseLifetime(const std::chrono::milliseconds &response_lifetime) { Response::response_lifetime_ = response_lifetime; } diff --git a/http-server/response.h b/http-server/response.h index cc8df9c6..51837556 100644 --- a/http-server/response.h +++ b/http-server/response.h @@ -13,8 +13,7 @@ * limitations under the License. */ -#ifndef ICN_WEB_SERVER_RESPONSE_H_ -#define ICN_WEB_SERVER_RESPONSE_H_ +#pragma once #include "common.h" @@ -25,8 +24,7 @@ class Response public: Response(); - virtual - ~Response(); + virtual ~Response(); size_t size(); @@ -41,8 +39,7 @@ class Response const std::chrono::milliseconds &getResponseLifetime() const; - void setResponseLifetime(const std::chrono::milliseconds &response_lifetime); - + virtual void setResponseLifetime(const std::chrono::milliseconds &response_lifetime); protected: boost::asio::streambuf streambuf_; @@ -51,6 +48,4 @@ class Response std::chrono::milliseconds response_lifetime_; }; -} // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_RESPONSE_H_ +} // end namespace icn_httpserver \ No newline at end of file diff --git a/http-server/socket_request.h b/http-server/socket_request.h index cc77ef73..657226a3 100644 --- a/http-server/socket_request.h +++ b/http-server/socket_request.h @@ -22,8 +22,7 @@ * SOFTWARE. */ -#ifndef ICN_WEB_SERVER_SOCKETREQUEST_H_ -#define ICN_WEB_SERVER_SOCKETREQUEST_H_ +#pragma once #include "request.h" @@ -40,5 +39,3 @@ class SocketRequest }; } // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_SOCKETREQUEST_H_ diff --git a/http-server/socket_response.h b/http-server/socket_response.h index 722e8196..e1a72142 100644 --- a/http-server/socket_response.h +++ b/http-server/socket_response.h @@ -22,8 +22,7 @@ * SOFTWARE. */ -#ifndef ICN_WEB_SERVER_SOCKETRESPONSE_H_ -#define ICN_WEB_SERVER_SOCKETRESPONSE_H_ +#pragma once #include "response.h" @@ -48,5 +47,3 @@ class SocketResponse }; } // end namespace icn_httpserver - -#endif // ICN_WEB_SERVER_SOCKETRESPONSE_H_ diff --git a/main.cc b/main.cc index e3b6e078..0a1c07a6 100644 --- a/main.cc +++ b/main.cc @@ -27,7 +27,8 @@ #include #include "http-server/http_server.h" -#include "http-client/http_client.h" +#include "http_client_tcp.h" +#include "http_client_icn.h" typedef icn_httpserver::HttpServer HttpServer; typedef icn_httpserver::Response Response; @@ -67,7 +68,7 @@ void afterSignal(HttpServer *webServer, const boost::system::error_code &errorCo } void usage(const char *programName) { - cerr << programName << " [-p PATH_TO_ROOT_FOOT_FOLDER] [-o TCP_LISTEN_PORT] [-l WEBSERVER_PREFIX] [-x PROXY_ADDRESS]\n" + cerr << programName << " [-p PATH_TO_ROOT_FOOT_FOLDER] [-o TCP_LISTEN_PORT] [-l WEBSERVER_PREFIX] [-x TCP_PROXY_ADDRESS] [-z ICN_PROXY_PREFIX]\n" << "Web server able to publish content and generate http responses over TCP/ICN\n" << endl; exit(1); @@ -78,12 +79,12 @@ int main(int argc, char **argv) { string root_folder = "/var/www/html"; string webserver_prefix = "http://webserver"; - string proxy_address = ""; + string tcp_proxy_address; + string icn_proxy_prefix; int port = 8080; int opt = 0; - while ((opt = getopt(argc, argv, "p:l:o:hx:")) != -1) { - + while ((opt = getopt(argc, argv, "p:l:o:hx:z:")) != -1) { switch (opt) { case 'p': root_folder = optarg; @@ -92,11 +93,14 @@ int main(int argc, char **argv) { webserver_prefix = optarg; break; case 'x': - proxy_address = optarg; + tcp_proxy_address = optarg; break; case 'o': port = atoi(optarg); break; + case 'z': + icn_proxy_prefix = optarg; + break; case 'h': default: usage(argv[0]); @@ -120,6 +124,12 @@ int main(int argc, char **argv) { std::cout << "Using web root folder: [" << root_folder << "]" << std::endl; std::cout << "Using locator: [" << webserver_prefix << "]" << std::endl; + if (!tcp_proxy_address.empty()) { + std::cout << "Using TCP proxy: [" << tcp_proxy_address << "]" << std::endl; + } + if (!icn_proxy_prefix.empty()) { + std::cout << "Using ICN proxy: [" << icn_proxy_prefix << "]" << std::endl; + } boost::asio::io_service io_service; HttpServer server(port, webserver_prefix, 50, 5, 300, io_service); @@ -147,16 +157,27 @@ int main(int argc, char **argv) { // Will respond with content in the web/-directory, and its subdirectories. // Default file: index.html // Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server - server.default_resource["GET"] = [&server, &root_folder, &proxy_address](shared_ptr response, shared_ptr request) { + server.default_resource["GET"] = [&server, &root_folder, &tcp_proxy_address, &icn_proxy_prefix] + (shared_ptr response, shared_ptr request) { const auto web_root_path = boost::filesystem::canonical(root_folder); boost::filesystem::path path = web_root_path; path /= request->getPath(); - if (path.extension().string() == ".mpd") { - response->setResponseLifetime(std::chrono::milliseconds(1000)); + auto socket_request = dynamic_cast(request.get()); + + std::chrono::milliseconds response_lifetime; + + if (path.extension().string() == ".mpd" || path.stem() == "latest") { + std::cout << "Setting lifetime to 1 second" << std::endl; + response_lifetime = std::chrono::milliseconds(1000); + } else { + std::cout << "Setting lifetime to 5 second" << std::endl; + response_lifetime = std::chrono::milliseconds(5000); } + response->setResponseLifetime(response_lifetime); + if (boost::filesystem::exists(path)) { path = boost::filesystem::canonical(path); @@ -175,7 +196,7 @@ int main(int argc, char **argv) { ifs->open(path.string(), ifstream::in | ios::binary); if (*ifs) { - //read and send 1 MB at a time + //read and send 15 MB at a time streamsize buffer_size = 15 * 1024 * 1024; auto buffer = make_shared >(buffer_size); @@ -184,17 +205,7 @@ int main(int argc, char **argv) { ifs->seekg(0, ios::beg); response->setResponseLength(length); - - icn_httpserver::SocketRequest - *socket_request = dynamic_cast(request.get()); - - if (socket_request) { - *response << "HTTP/1.0 200 OK\r\nContent-Length: " << length << "\r\n\r\n"; - } - - if (path.extension().string() == ".mpd") { - response->setResponseLifetime(std::chrono::milliseconds(1000)); - } + *response << "HTTP/1.0 200 OK\r\nContent-Length: " << length << "\r\n\r\n"; default_resource_send(server, response, ifs, buffer, length); @@ -205,31 +216,54 @@ int main(int argc, char **argv) { } } - if (!proxy_address.empty()) { + string proxy; + HTTPClient* client = nullptr; + + if (tcp_proxy_address.empty() && !icn_proxy_prefix.empty()) { + proxy = icn_proxy_prefix; + client = new HTTPClientIcn(20); + } else if (!tcp_proxy_address.empty() && icn_proxy_prefix.empty()) { + proxy = tcp_proxy_address; + client = new HTTPClientTcp; + } else if (!tcp_proxy_address.empty() && !icn_proxy_prefix.empty()) { + if (socket_request) { + proxy = icn_proxy_prefix; + client = new HTTPClientIcn(20); + } else { + proxy = tcp_proxy_address; + client = new HTTPClientTcp; + } + } + if (!proxy.empty()) { // Fetch content from remote origin std::stringstream ss; - if (strncmp("http://", proxy_address.c_str(), 7) || strncmp("https://", proxy_address.c_str(), 8)) { - ss << "http://"; + + if (strncmp("http://", proxy.c_str(), 7) != 0) { + if (strncmp("https://", proxy.c_str(), 8) != 0) { + ss << "https://"; + } else { + ss << "http://"; + } } - ss << proxy_address; + ss << proxy; ss << request->getPath(); - std::cout << ss.str() << std::endl; + std::cout << "Forwarding request to " << ss.str() << std::endl; - HTTPClient client; + client->download(ss.str(), *response); - client.download(ss.str(), *response); + delete client; -// std::cout << "+++++++++++++++++++++++++++++++++++" << reply.size() << std::endl; - -// *response << reply; + if (response->size() == 0) { + *response << "HTTP/1.1 504 Gateway Timeout\r\n\r\n"; + } return; } - string content = "Could not open path " + request->getPath(); + string content = "Could not open path " + request->getPath() + "\n"; *response << "HTTP/1.1 404 Not found\r\nContent-Length: " << content.length() << "\r\n\r\n" << content; diff --git a/scripts/build-package.sh b/scripts/build-package.sh index f13b894a..1d58760a 100644 --- a/scripts/build-package.sh +++ b/scripts/build-package.sh @@ -32,16 +32,8 @@ name=Repo for cmake3 baseurl=http://mirror.ghettoforge.org/distributions/gf/el/7/plus/x86_64/ enabled=1 gpgcheck=0 -EOF - sudo cat << EOF > jsoncpp.repo -[jsoncp-repo] -name=Repo for jsoncpp -baseurl=http://dl.fedoraproject.org/pub/epel/7/x86_64/ -enabled=1 -gpgcheck=0 EOF sudo mv cmake.repo /etc/yum.repos.d/cmake.repo - sudo mv jsoncpp.repo /etc/yum.repos.d/jsoncpp.repo fi } -- cgit 1.2.3-korg