diff options
-rw-r--r-- | CMakeLists.txt | 48 | ||||
-rw-r--r-- | cmake/Modules/FindCURL.cmake | 69 | ||||
-rw-r--r-- | cmake/Modules/FindLibhicnet.cmake | 39 | ||||
-rw-r--r-- | cmake/Modules/FindLibicnet.cmake | 2 | ||||
-rw-r--r-- | config.h.in | 19 | ||||
-rw-r--r-- | dockerfile.ubuntu.xenial | 31 | ||||
-rw-r--r-- | http-client/http_client.cc | 59 | ||||
-rw-r--r-- | http-client/http_client.h | 35 | ||||
-rw-r--r-- | http-server/common.h | 15 | ||||
-rw-r--r-- | http-server/http_server.cc | 144 | ||||
-rw-r--r-- | http-server/http_server.h | 16 | ||||
-rw-r--r-- | http-server/icn_request.cc | 16 | ||||
-rw-r--r-- | http-server/icn_request.h | 10 | ||||
-rw-r--r-- | http-server/icn_response.cc | 15 | ||||
-rw-r--r-- | http-server/icn_response.h | 4 | ||||
-rw-r--r-- | main.cc | 41 | ||||
-rw-r--r-- | scripts/build-package.sh | 5 |
17 files changed, 404 insertions, 164 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d243842..f909c9c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,17 +13,39 @@ cmake_minimum_required(VERSION 3.2) project(http-server) +set(CMAKE_CXX_STANDARD 11) + +if (NOT CMAKE_BUILD_TYPE) + message(STATUS "No build type selected, default to Release") + set(CMAKE_BUILD_TYPE "Release") +endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") -find_package(Libicnet REQUIRED) -include_directories(${LIBICNET_INCLUDE_DIRS}) +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) +else() + find_package(Libicnet REQUIRED) + set (TRANSPORT_LIBRARY ICNET) +endif() + +configure_file("${PROJECT_SOURCE_DIR}/config.h.in" + "${CMAKE_BINARY_DIR}/config.h") + +include_directories(${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIRS}) find_package(Threads REQUIRED) +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIRS}) + find_package(Boost 1.53.0 COMPONENTS regex system filesystem REQUIRED) -include_directories(SYSTEM ${Boost_INCLUDE_DIR} ${LIBICNET_INCLUDE_DIR}) +include_directories(SYSTEM ${Boost_INCLUDE_DIR} ${CMAKE_BINARY_DIR} ${CURL_INCLUDE_DIRS} ${LIB${TRANSPORT_LIBRARY}_INCLUDE_DIR}) set(SOURCE_FILES main.cc @@ -45,10 +67,18 @@ set(SOURCE_FILES http-server/socket_request.cc http-server/socket_request.h http-server/configuration.cc - http-server/configuration.h) + http-server/configuration.h + http-client/http_client.cc + http-client/http_client.h + ${CMAKE_BINARY_DIR}/config.h) + +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(http-server ${SOURCE_FILES}) -target_link_libraries(http-server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${LIBICNET_LIBRARY}) +target_link_libraries(http-server ${LIB${TRANSPORT_LIBRARY}_LIBRARY} ${CURL_LIBRARY} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS http-server DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) @@ -74,19 +104,21 @@ execute_process(COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/version OUTPUT_VARIABLE PACKAGE_VERSION) string(STRIP ${PACKAGE_VERSION} PACKAGE_VERSION) +string(TOLOWER ${TRANSPORT_LIBRARY} TRANSPORT_DEPENDENCY) + if (DEB_PACKAGE) set(TYPE "DEBIAN") set(GENERATOR "DEB") set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME}_${PACKAGE_VERSION}_${ARCHITECTURE}") set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) - set(CPACK_${TYPE}_PACKAGE_DEPENDS "libicnet (>= 1.0)") + set(CPACK_${TYPE}_PACKAGE_DEPENDS "lib${TRANSPORT_DEPENDENCY} (>= 0.1)") elseif (RPM_PACKAGE) set(TYPE "RPM") set(GENERATOR "RPM") set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME}-${PACKAGE_VERSION}.${ARCHITECTURE}") set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/etc" "/usr/lib/python2.7" "/usr/lib/python2.7/site-packages") set(CPACK_${TYPE}_PACKAGE_AUTOREQ ON) - set(CPACK_${TYPE}_PACKAGE_REQUIRES "boost-system >= 1.53, boost-regex >= 1.53, boost-filesystem >= 1.53, libicnet >= 1.0") + set(CPACK_${TYPE}_PACKAGE_REQUIRES "boost-system >= 1.53, boost-regex >= 1.53, boost-filesystem >= 1.53, lib${TRANSPORT_DEPENDENCY} >= 1.0") else () return() endif () diff --git a/cmake/Modules/FindCURL.cmake b/cmake/Modules/FindCURL.cmake new file mode 100644 index 00000000..239b0e50 --- /dev/null +++ b/cmake/Modules/FindCURL.cmake @@ -0,0 +1,69 @@ +#.rst: +# FindCURL +# -------- +# +# Find curl +# +# Find the native CURL headers and libraries. +# +# :: +# +# CURL_INCLUDE_DIRS - where to find curl_/curl_.h, etc. +# CURL_LIBRARIES - List of libraries when using curl. +# CURL_FOUND - True if curl found. +# CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8) + +#============================================================================= +# Copyright 2006-2009 Kitware, Inc. +# Copyright 2012 Rolf Eike Beer <eike@sf-mail.de> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# Look for the header file. +find_path(CURL_INCLUDE_DIR NAMES curl/curl.h) +mark_as_advanced(CURL_INCLUDE_DIR) + +# Look for the library (sorted from most current/relevant entry to least). +find_library(CURL_LIBRARY NAMES + curl + # Windows MSVC prebuilts: + curllib + libcurl_imp + curllib_static + # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip): + libcurl + ) +mark_as_advanced(CURL_LIBRARY) + +if(CURL_INCLUDE_DIR) + foreach(_curl_version_header curlver.h curl.h) + if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}") + file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"") + + string(REGEX REPLACE "^#define[\t ]+LIBCURL_VERSION[\t ]+\"([^\"]*)\".*" "\\1" CURL_VERSION_STRING "${curl_version_str}") + unset(curl_version_str) + break() + endif() + endforeach() +endif() + +# handle the QUIETLY and REQUIRED arguments and set CURL_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL + REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR + VERSION_VAR CURL_VERSION_STRING) + +if(CURL_FOUND) + set(CURL_LIBRARIES ${CURL_LIBRARY}) + set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) +endif() diff --git a/cmake/Modules/FindLibhicnet.cmake b/cmake/Modules/FindLibhicnet.cmake new file mode 100644 index 00000000..0d4f5fbc --- /dev/null +++ b/cmake/Modules/FindLibhicnet.cmake @@ -0,0 +1,39 @@ +######################################## +# +# 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/cmake/Modules/FindLibicnet.cmake b/cmake/Modules/FindLibicnet.cmake index 3c9c4f5f..bfb81ef7 100644 --- a/cmake/Modules/FindLibicnet.cmake +++ b/cmake/Modules/FindLibicnet.cmake @@ -22,7 +22,7 @@ set(LIBICNET_SEARCH_PATH_LIST /usr ) -find_path(LIBICNET_INCLUDE_DIR icnet/icnet_common.h +find_path(LIBICNET_INCLUDE_DIR icnet/icnet_ccnx_common.h HINTS ${LIBICNET_SEARCH_PATH_LIST} PATH_SUFFIXES include DOC "Find the libicnet includes") diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..d10e62ee --- /dev/null +++ b/config.h.in @@ -0,0 +1,19 @@ +/* + * 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 + +#cmakedefine ICNET +#cmakedefine HICNET diff --git a/dockerfile.ubuntu.xenial b/dockerfile.ubuntu.xenial new file mode 100644 index 00000000..42f141c5 --- /dev/null +++ b/dockerfile.ubuntu.xenial @@ -0,0 +1,31 @@ +# Ubuntu Dockerfile +# +# https://github.com/dockerfile/ubuntu +# + +# Pull base image. +FROM ubuntu:xenial + +# Building tools and dependencies +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 && \ + 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 \ + libhicnet-dev libhicn-dev libcurl4-openssl-dev \ + libboost-system-dev libboost-regex-dev libboost-filesystem-dev && \ + rm -rf /var/lib/apt/lists/* + +# Cmake version 3.8 +ENV CMAKE_INSTALL_SCRIPT_URL="https://cmake.org/files/v3.8/cmake-3.8.0-Linux-x86_64.sh" +ENV CMAKE_INSTALL_SCRIPT="/tmp/install_cmake.sh" +ENV CMAKE_INSTALL_LOCATION="/usr" + +RUN curl ${CMAKE_INSTALL_SCRIPT_URL} > ${CMAKE_INSTALL_SCRIPT} +RUN mkdir -p ${CMAKE_INSTALL_LOCATION} +RUN bash ${CMAKE_INSTALL_SCRIPT} --skip-license --prefix=${CMAKE_INSTALL_LOCATION} --exclude-subdir diff --git a/http-client/http_client.cc b/http-client/http_client.cc new file mode 100644 index 00000000..221e7bbe --- /dev/null +++ b/http-client/http_client.cc @@ -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. + */ + +#include "http_client.h" + +#include <curl/curl.h> +#include <sstream> +#include <iostream> + +using namespace std; + +size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) { + ((ostream*) stream)->write((const char*)ptr, size * nmemb); + return size * nmemb; +} + +HTTPClient::HTTPClient() { + curl_ = curl_easy_init(); +} + +HTTPClient::~HTTPClient() { + curl_easy_cleanup(curl_); +} + +bool HTTPClient::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); + curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &out); + + /* 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; +}
\ No newline at end of file diff --git a/http-client/http_client.h b/http-client/http_client.h new file mode 100644 index 00000000..19d3c41e --- /dev/null +++ b/http-client/http_client.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. + */ + +#ifndef HTTP_CLIENT_H_ +#define HTTP_CLIENT_H_ + +#include <string> + +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_; +}; + +#endif // HTTP_CLIENT_H_
\ No newline at end of file diff --git a/http-server/common.h b/http-server/common.h index e69706e6..580f8a41 100644 --- a/http-server/common.h +++ b/http-server/common.h @@ -16,6 +16,18 @@ #ifndef ICN_WEB_SERVER_COMMON_H_ #define ICN_WEB_SERVER_COMMON_H_ +#include "config.h" + +#if defined(HICNET) + #include <hicnet/hicnet_http_facade.h> + #include <hicnet/hicnet_utils_hash.h> +#elif defined(ICNET) + #include <icnet/icnet_http_facade.h> + #include <icnet/icnet_utils_hash.h> +#else + #error "No ICN tranport library to which link against." +#endif + #include <boost/asio.hpp> #include <boost/regex.hpp> #include <boost/algorithm/string/predicate.hpp> @@ -31,9 +43,6 @@ #include <sstream> #include <string> -// ICN extensions -#include <icnet/icnet_socket_producer.h> - typedef boost::asio::ip::tcp::socket socket_type; typedef std::function<void(const boost::system::error_code &)> SendCallback; diff --git a/http-server/http_server.cc b/http-server/http_server.cc index ebc8503b..6bdf18f2 100644 --- a/http-server/http_server.cc +++ b/http-server/http_server.cc @@ -33,7 +33,6 @@ HttpServer::HttpServer(unsigned short port, internal_io_service_(std::make_shared<boost::asio::io_service>()), io_service_(*internal_io_service_), acceptor_(io_service_), - acceptor_producer_(std::make_shared<icnet::ProducerSocket>(icnet::Name(icn_name))), timeout_request_(timeout_request), timeout_content_(timeout_send_or_receive) { } @@ -48,124 +47,51 @@ HttpServer::HttpServer(unsigned short port, icn_name_(icn_name), io_service_(ioService), acceptor_(io_service_), - acceptor_producer_(std::make_shared<icnet::ProducerSocket>(icnet::Name(icn_name))), timeout_request_(timeout_request), timeout_content_(timeout_send_or_receive) { } -void HttpServer::processIncomingInterest(icnet::ProducerSocket &p, const icnet::Interest &interest) { - icnet::Name complete_name = interest.getName(); +void HttpServer::onIcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher> &publisher, + const uint8_t *buffer, + std::size_t size) { + publisher->setTimeout(5); + std::shared_ptr<Request> request = std::make_shared<IcnRequest>(publisher); + request->getContent().rdbuf()->sputn((char*)buffer, size); - if (complete_name.getSegmentCount() <= 2) { - std::cerr << "Received malformed name " << complete_name << ". Ignoring it." << std::endl; + if (!parse_request(request, request->getContent())) { return; } - icnet::Name request_name = complete_name.get(-1).isSegment() ? complete_name.getPrefix(-1) : complete_name; + int request_id = libl4::utils::Hash::hash32(buffer, size); + + std::cout << "Request ID" << request_id << std::endl; std::unique_lock<std::mutex> lock(thread_list_mtx_); - if (icn_producers_.size() < config_.getNum_threads()) { - if (icn_producers_.find(request_name) == icn_producers_.end()) { - std::cout << "Received interest name: " << request_name << std::endl; - std::shared_ptr<icnet::ProducerSocket> p = makeProducer(request_name); - icn_producers_[request_name] = p; + if (icn_publishers_.size() < config_.getNum_threads()) { + if (icn_publishers_.find(request_id) == icn_publishers_.end()) { + std::cout << "Received request for: " << request->getPath() << std::endl; + icn_publishers_[request_id] = publisher; std::cout << "Starting new thread" << std::endl; - std::thread t([this, interest, request_name, p]() { - processInterest(request_name, p); + io_service_.dispatch([this, request, request_id]() { + find_resource(nullptr, request); + icn_publishers_[request_id]->serveClients(); + std::unique_lock<std::mutex> lock(thread_list_mtx_); + icn_publishers_.erase(request_id); }); - t.detach(); - } else { - icn_producers_[request_name]->onInterest(complete_name, interest); } } } -void HttpServer::signPacket(icnet::ProducerSocket &p, icnet::ContentObject &content_object) { - // This is not really signing the packet. Signing every packet is cpu expensive. - icnet::KeyLocator keyLocator; - content_object.signWithSha256(keyLocator); -} - -void HttpServer::processInterest(icnet::Name request_name, std::shared_ptr<icnet::ProducerSocket> p) { - // Create timer - std::shared_ptr<icnet::ccnx::Portal> portal; - p->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(); - } - }; - - t.async_wait(wait_callback); - - // 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); - } - - std::function<void(icnet::ProducerSocket &p, const icnet::Interest &interest)> - interest_enter_callback = [this, &wait_callback, &t](icnet::ProducerSocket &p, const icnet::Interest &interest) { - t.cancel(); - t.expires_from_now(boost::posix_time::seconds(5)); - t.async_wait(wait_callback); - }; - - p->setSocketOption(icnet::ProducerCallbacksOptions::INTEREST_INPUT, - (icnet::ProducerInterestCallback) interest_enter_callback); - - // TODO The parsing of the parameters in theURL is missing! - if (method == GET) { - // Build new GET request to submit to the server - - std::shared_ptr<Request> request = std::make_shared<IcnRequest>(p, request_name.toString(), path, method, "1.0"); - - std::static_pointer_cast<IcnRequest>(request)->getHeader() - .insert(std::make_pair(std::string("Host"), std::string("localhost"))); - - p->attach(); - - find_resource(nullptr, request); - } - - p->serveForever(); - - std::unique_lock<std::mutex> lock(thread_list_mtx_); - icn_producers_.erase(request_name); -} - -std::shared_ptr<icnet::ProducerSocket> HttpServer::makeProducer(icnet::Name request_name) { - std::shared_ptr<icnet::ProducerSocket> producer = std::make_shared<icnet::ProducerSocket>(request_name); - // producer->setContextOption(FAST_SIGNING, true); - // producer->setContextOption(DATA_TO_SECURE, (api::ProducerDataCallback) bind(&http-server::signPacket, this, _1, _2)); - producer->setSocketOption(icnet::GeneralTransportOptions::DATA_PACKET_SIZE, PACKET_SIZE); - producer->setSocketOption(icnet::GeneralTransportOptions::OUTPUT_BUFFER_SIZE, SEND_BUFFER_SIZE); - - return producer; -} - void HttpServer::setIcnAcceptor() { - acceptor_producer_->setSocketOption(icnet::ProducerCallbacksOptions::INTEREST_INPUT, - (icnet::ProducerInterestCallback) bind(&HttpServer::processIncomingInterest, - this, - std::placeholders::_1, - std::placeholders::_2)); - acceptor_producer_->dispatch(); + icn_acceptor_ = std::make_shared<libl4::http::HTTPServerAcceptor>(icn_name_, std::bind(&HttpServer::onIcnRequest, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3)); + icn_acceptor_->listen(true); } -void HttpServer::spawnTcpThreads() { +void HttpServer::spawnThreads() { if (io_service_.stopped()) { io_service_.reset(); } @@ -216,11 +142,9 @@ void HttpServer::start() { } } - spawnTcpThreads(); + spawnThreads(); setIcnAcceptor(); - - // Wait for the rest of the threads, if any, to finish as well for (auto &t: socket_threads_) { t.join(); @@ -233,16 +157,14 @@ void HttpServer::start() { void HttpServer::stop() { acceptor_.close(); - acceptor_producer_.reset(); + icn_acceptor_.reset(); io_service_.stop(); - for (auto p: icn_producers_) { - std::shared_ptr<icnet::ccnx::Portal> portalPtr; - p.second->getSocketOption(icnet::GeneralTransportOptions::PORTAL, portalPtr); - portalPtr->getIoService().stop(); + for (auto &p: icn_publishers_) { + p.second->stop(); } - for (auto p : icn_producers_) { + for (auto p : icn_publishers_) { p.second.reset(); } @@ -289,7 +211,7 @@ void HttpServer::read_request_and_content(std::shared_ptr<socket_type> socket) { std::shared_ptr<Request> request = std::make_shared<SocketRequest>(); request->read_remote_endpoint_data(*socket); - //Set timeout on the following boost::asio::async-read or write function + // Set timeout on the following boost::asio::async-read or write function std::shared_ptr<boost::asio::deadline_timer> timer; if (timeout_request_ > 0) { timer = set_timeout_on_socket(socket, timeout_request_); @@ -439,7 +361,7 @@ void HttpServer::write_response(std::shared_ptr<socket_type> socket, if (socket) { resp = new SocketResponse(socket); } else { - resp = new IcnResponse(std::static_pointer_cast<IcnRequest>(request)->getProducer(), + resp = new IcnResponse(std::static_pointer_cast<IcnRequest>(request)->getHttpPublisher(), std::static_pointer_cast<IcnRequest>(request)->getName(), std::static_pointer_cast<IcnRequest>(request)->getPath(), std::static_pointer_cast<IcnRequest>(request)->getRequest_id()); diff --git a/http-server/http_server.h b/http-server/http_server.h index fbc841c7..704863d5 100644 --- a/http-server/http_server.h +++ b/http-server/http_server.h @@ -74,13 +74,9 @@ class HttpServer { std::unordered_map<std::string, ResourceCallback> default_resource; private: - void processInterest(icnet::Name request_name, std::shared_ptr<icnet::ProducerSocket> p); + void onIcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher>& publisher, const uint8_t* buffer, std::size_t size); - void processIncomingInterest(icnet::ProducerSocket &p, const icnet::Interest &interest); - - void signPacket(icnet::ProducerSocket &p, icnet::ContentObject &content_object); - - void spawnTcpThreads(); + void spawnThreads(); void setIcnAcceptor(); @@ -96,8 +92,6 @@ class HttpServer { std::shared_ptr<Request> request, ResourceCallback &resource_function); - std::shared_ptr<icnet::ProducerSocket> makeProducer(icnet::Name request_name); - Configuration config_; std::vector<std::pair<std::string, std::vector<std::pair<boost::regex, ResourceCallback> > > > opt_resource_; @@ -109,10 +103,8 @@ class HttpServer { // ICN parameters std::string icn_name_; - std::shared_ptr<icnet::ProducerSocket> acceptor_producer_; - std::unordered_map<icnet::Name, std::future<void>> icn_threads_; - std::unordered_map<icnet::Name, std::shared_ptr<icnet::ProducerSocket>> icn_producers_; - std::unordered_map<icnet::Name, std::shared_ptr<boost::asio::io_service>> name_io_service_map_; + std::shared_ptr<libl4::http::HTTPServerAcceptor> icn_acceptor_; + std::unordered_map<int, std::shared_ptr<libl4::http::HTTPServerPublisher>> icn_publishers_; std::mutex thread_list_mtx_; long timeout_request_; diff --git a/http-server/icn_request.cc b/http-server/icn_request.cc index 07d95a22..1709e917 100644 --- a/http-server/icn_request.cc +++ b/http-server/icn_request.cc @@ -17,19 +17,19 @@ namespace icn_httpserver { -IcnRequest::IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer) - : producer_(producer) { +IcnRequest::IcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher>& publisher) + : publisher_(publisher) { time_t t; time(&t); srand((unsigned int) t); request_id_ = rand(); } -IcnRequest::IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer, +IcnRequest::IcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher>& publisher, std::string name, std::string path, std::string method, std::string http_version) - : IcnRequest(producer) { + : IcnRequest(publisher) { this->name_ = name; this->path_ = path; this->method_ = method; @@ -52,12 +52,12 @@ void IcnRequest::setRequest_id(int request_id) { IcnRequest::request_id_ = request_id; } -const std::shared_ptr<icnet::ProducerSocket> &IcnRequest::getProducer() const { - return producer_; +const std::shared_ptr<libl4::http::HTTPServerPublisher> &IcnRequest::getHttpPublisher() const { + return publisher_; } -void IcnRequest::setProducer(const std::shared_ptr<icnet::ProducerSocket> &producer) { - IcnRequest::producer_ = producer; +void IcnRequest::setProducer(const std::shared_ptr<libl4::http::HTTPServerPublisher> &producer) { + IcnRequest::publisher_ = producer; } } // end namespace icn_httpserver diff --git a/http-server/icn_request.h b/http-server/icn_request.h index c5aa10e4..ec9ee198 100644 --- a/http-server/icn_request.h +++ b/http-server/icn_request.h @@ -24,9 +24,9 @@ namespace icn_httpserver { class IcnRequest : public Request { public: - IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer); + IcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher>& publisher); - IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer, + IcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher>& publisher, std::string name, std::string path, std::string method, @@ -40,14 +40,14 @@ class IcnRequest void setRequest_id(int request_id); - const std::shared_ptr<icnet::ProducerSocket> &getProducer() const; + const std::shared_ptr<libl4::http::HTTPServerPublisher> &getHttpPublisher() const; - void setProducer(const std::shared_ptr<icnet::ProducerSocket> &producer); + void setProducer(const std::shared_ptr<libl4::http::HTTPServerPublisher> &producer); private: std::string name_; int request_id_; - std::shared_ptr<icnet::ProducerSocket> producer_; + std::shared_ptr<libl4::http::HTTPServerPublisher> publisher_; }; diff --git a/http-server/icn_response.cc b/http-server/icn_response.cc index 6fe8b1e1..241eda51 100644 --- a/http-server/icn_response.cc +++ b/http-server/icn_response.cc @@ -17,22 +17,23 @@ namespace icn_httpserver { -IcnResponse::IcnResponse(std::shared_ptr<icnet::ProducerSocket> producer, +IcnResponse::IcnResponse(std::shared_ptr<libl4::http::HTTPServerPublisher> publisher, std::string ndn_name, std::string ndn_path, int response_id) - : producer_(producer), ndn_name_(ndn_name), ndn_path_(ndn_path), response_id_(response_id) { + : publisher_(publisher), ndn_name_(ndn_name), ndn_path_(ndn_path), response_id_(response_id) { } void IcnResponse::send(const SendCallback &callback) { std::size_t buffer_size = this->streambuf_.size(); this->streambuf_.commit(this->streambuf_.size()); - this->producer_->produce(icnet::Name(/*this->ndn_name*/), - boost::asio::buffer_cast<const uint8_t *>(this->streambuf_.data()), - buffer_size, - this->response_id_, - this->is_last_); + std::cout << "Rrsponse Id " << response_id_ << std::endl; + + this->publisher_->publishContent(boost::asio::buffer_cast<const uint8_t *>(this->streambuf_.data()), + buffer_size, + this->response_id_, + this->is_last_); this->streambuf_.consume(buffer_size); diff --git a/http-server/icn_response.h b/http-server/icn_response.h index e9af0d40..13a75629 100644 --- a/http-server/icn_response.h +++ b/http-server/icn_response.h @@ -25,7 +25,7 @@ class IcnResponse public: - IcnResponse(std::shared_ptr<icnet::ProducerSocket> producer, + IcnResponse(std::shared_ptr<libl4::http::HTTPServerPublisher> producer, std::string ndn_name, std::string ndn_path, int response_id); @@ -36,7 +36,7 @@ class IcnResponse std::string ndn_name_; std::string ndn_path_; int response_id_; - std::shared_ptr<icnet::ProducerSocket> producer_; + std::shared_ptr<libl4::http::HTTPServerPublisher> publisher_; }; } // end namespace icn_httpserver @@ -27,6 +27,7 @@ #include <boost/filesystem.hpp> #include "http-server/http_server.h" +#include "http-client/http_client.h" typedef icn_httpserver::HttpServer HttpServer; typedef icn_httpserver::Response Response; @@ -66,7 +67,7 @@ void afterSignal(HttpServer *webServer, const boost::system::error_code &errorCo } void usage(const char *programName) { - cerr << programName << " [-p PATH_TO_ROOT_FOOT_FOLDER] [-l WEBSERVER_PREFIX]\n" + cerr << programName << " [-p PATH_TO_ROOT_FOOT_FOLDER] [-l WEBSERVER_PREFIX] [-x PROXY_ADDRESS]\n" << "Web server able to publish content and generate http responses over TCP/ICN\n" << endl; exit(1); @@ -76,11 +77,12 @@ int main(int argc, char **argv) { // Parse command line arguments string root_folder = "/var/www/html"; - string webserver_prefix = "ccnx:/webserver"; + string webserver_prefix = "http://webserver"; + string proxy_address = ""; int opt = 0; - while ((opt = getopt(argc, argv, "p:l:h")) != -1) { + while ((opt = getopt(argc, argv, "p:l:hx:")) != -1) { switch (opt) { case 'p': @@ -89,7 +91,11 @@ int main(int argc, char **argv) { case 'l': webserver_prefix = optarg; break; + case 'x': + proxy_address = optarg; + break; case 'h': + default: usage(argv[0]); break; } @@ -138,7 +144,7 @@ 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](shared_ptr<Response> response, shared_ptr<Request> request) { + server.default_resource["GET"] = [&server, &root_folder, &proxy_address](shared_ptr<Response> response, shared_ptr<Request> request) { const auto web_root_path = boost::filesystem::canonical(root_folder); boost::filesystem::path path = web_root_path; @@ -164,7 +170,7 @@ int main(int argc, char **argv) { if (*ifs) { //read and send 1 MB at a time streamsize buffer_size = 15 * 1024 * 1024; - auto buffer = make_shared < vector < char > > (buffer_size); + auto buffer = make_shared<vector<char> >(buffer_size); ifs->seekg(0, ios::end); auto length = ifs->tellg(); @@ -182,11 +188,36 @@ int main(int argc, char **argv) { default_resource_send(server, response, ifs, buffer, length); return; + } } } } + if (!proxy_address.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://"; + } + + ss << proxy_address; + ss << request->getPath(); + + std::cout << ss.str() << std::endl; + + HTTPClient client; + + client.download(ss.str(), *response); + +// std::cout << "+++++++++++++++++++++++++++++++++++" << reply.size() << std::endl; + +// *response << reply; + + return; + } + string content = "Could not open path " + request->getPath(); *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 e459c969..f13b894a 100644 --- a/scripts/build-package.sh +++ b/scripts/build-package.sh @@ -8,12 +8,12 @@ apt_get=${APT_PATH:-"/usr/local/bin/apt-get"} BUILD_TOOLS_UBUNTU="build-essential cmake" LIBSSL_LIBEVENT_UBUNTU="libevent-dev libssl-dev" -DEPS_UBUNTU="$LIBSSL_LIBEVENT_UBUNTU longbow-dev libparc-dev libccnx-common-dev libccnx-transport-rta-dev libicnet-dev libboost-system-dev libboost-regex-dev libboost-filesystem-dev" +DEPS_UBUNTU="$LIBSSL_LIBEVENT_UBUNTU libcurl4-openssl-dev longbow-dev libparc-dev libccnx-common-dev libccnx-transport-rta-dev libicnet-dev libboost-system-dev libboost-regex-dev libboost-filesystem-dev" BUILD_TOOLS_GROUP_CENTOS="'Development Tools'" BUILD_TOOLS_SINGLE_CENTOS="cmake" LIBSSL_LIBEVENT_CENTOS="libevent-devel openssl-devel" -DEPS_CENTOS="$LIBSSL_LIBEVENT_CENTOS longbow-devel libparc-devel libccnx-common-devel libccnx-transport-rta-devel libicnet-devel boost-devel" +DEPS_CENTOS="$LIBSSL_LIBEVENT_CENTOS curl-devel longbow-devel libparc-devel libccnx-common-devel libccnx-transport-rta-devel libicnet-devel boost-devel" # Parameters: # $1 = Distribution [Trusty / CentOS] @@ -118,6 +118,7 @@ EOF echo "Distribution $DISTRIB_CODENAME is not supported" exit -1 fi + } setup() { |