aboutsummaryrefslogtreecommitdiffstats
path: root/http-server
diff options
context:
space:
mode:
authorMauro Sardara <msardara+fdio@cisco.com>2017-02-22 23:24:21 +0100
committerMauro Sardara <msardara+fdio@cisco.com>2017-02-22 23:24:21 +0100
commit975b5709addd72cba7184f94f2805f1c42e07dbe (patch)
treef89f813f04f6ba3f7558ba7bb9f07df1f9bdccef /http-server
parent9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff)
First commit: http-server
Change-Id: Ia527fe3065016404b0ea752ddc9e15c96288ed86 Signed-off-by: Mauro Sardara <msardara+fdio@cisco.com>
Diffstat (limited to 'http-server')
-rw-r--r--http-server/common.h40
-rw-r--r--http-server/configuration.cc56
-rw-r--r--http-server/configuration.h52
-rw-r--r--http-server/content.cc34
-rw-r--r--http-server/content.h38
-rw-r--r--http-server/http_server.cc487
-rw-r--r--http-server/http_server.h125
-rw-r--r--http-server/icn_request.cc63
-rw-r--r--http-server/icn_request.h56
-rw-r--r--http-server/icn_response.cc44
-rw-r--r--http-server/icn_response.h44
-rw-r--r--http-server/request.cc64
-rw-r--r--http-server/request.h83
-rw-r--r--http-server/response.cc44
-rw-r--r--http-server/response.h50
-rw-r--r--http-server/socket_request.cc37
-rw-r--r--http-server/socket_request.h44
-rw-r--r--http-server/socket_response.cc54
-rw-r--r--http-server/socket_response.h52
19 files changed, 1467 insertions, 0 deletions
diff --git a/http-server/common.h b/http-server/common.h
new file mode 100644
index 00000000..e69706e6
--- /dev/null
+++ b/http-server/common.h
@@ -0,0 +1,40 @@
+/*
+ * 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 ICN_WEB_SERVER_COMMON_H_
+#define ICN_WEB_SERVER_COMMON_H_
+
+#include <boost/asio.hpp>
+#include <boost/regex.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/functional/hash.hpp>
+#include <memory>
+#include <algorithm>
+
+#include <unordered_map>
+#include <thread>
+#include <future>
+#include <functional>
+#include <iostream>
+#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;
+
+#endif // ICN_WEB_SERVER_COMMON_H_
diff --git a/http-server/configuration.cc b/http-server/configuration.cc
new file mode 100644
index 00000000..8f205a0a
--- /dev/null
+++ b/http-server/configuration.cc
@@ -0,0 +1,56 @@
+/*
+ * 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 "configuration.h"
+
+namespace icn_httpserver {
+
+Configuration::Configuration(unsigned short port, size_t num_threads)
+ : num_threads_(num_threads), port_(port), reuse_address_(true) {
+}
+
+size_t Configuration::getNum_threads() const {
+ return num_threads_;
+}
+
+void Configuration::setNum_threads(size_t num_threads) {
+ Configuration::num_threads_ = num_threads;
+}
+
+unsigned short Configuration::getPort() const {
+ return port_;
+}
+
+void Configuration::setPort(unsigned short port) {
+ Configuration::port_ = port;
+}
+
+const std::string &Configuration::getAddress() const {
+ return address_;
+}
+
+void Configuration::setAddress(const std::string &address) {
+ Configuration::address_ = address;
+}
+
+bool Configuration::isReuse_address() const {
+ return reuse_address_;
+}
+
+void Configuration::setReuse_address(bool reuse_address) {
+ Configuration::reuse_address_ = reuse_address;
+}
+
+} // end namespace icn_httpserver \ No newline at end of file
diff --git a/http-server/configuration.h b/http-server/configuration.h
new file mode 100644
index 00000000..65d3170a
--- /dev/null
+++ b/http-server/configuration.h
@@ -0,0 +1,52 @@
+/*
+ * 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 ICN_WEB_SERVER_CONFIGURATION_H_
+#define ICN_WEB_SERVER_CONFIGURATION_H_
+
+#include "common.h"
+
+namespace icn_httpserver {
+
+class Configuration {
+ public:
+ Configuration(unsigned short port, size_t num_threads);
+
+ size_t getNum_threads() const;
+
+ void setNum_threads(size_t num_threads);
+
+ unsigned short getPort() const;
+
+ void setPort(unsigned short port);
+
+ const std::string &getAddress() const;
+
+ void setAddress(const std::string &address);
+
+ bool isReuse_address() const;
+
+ void setReuse_address(bool reuse_address);
+
+ private:
+ size_t num_threads_;
+ unsigned short port_;
+ std::string address_;
+ bool reuse_address_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_CONFIGURATION_H_
diff --git a/http-server/content.cc b/http-server/content.cc
new file mode 100644
index 00000000..f6bd0483
--- /dev/null
+++ b/http-server/content.cc
@@ -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.
+ */
+
+#include "content.h"
+
+namespace icn_httpserver {
+
+Content::Content(boost::asio::streambuf &streambuf)
+ : std::istream(&streambuf), streambuf_(streambuf) {
+}
+
+std::size_t Content::size() {
+ return streambuf_.size();
+}
+
+std::string Content::string() {
+ std::stringstream ss;
+ ss << rdbuf();
+ return ss.str();
+}
+
+} // end namespace icn_httpserver \ No newline at end of file
diff --git a/http-server/content.h b/http-server/content.h
new file mode 100644
index 00000000..a81ad643
--- /dev/null
+++ b/http-server/content.h
@@ -0,0 +1,38 @@
+/*
+ * 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 "common.h"
+
+#ifndef ICN_WEB_SERVER_CONTENT_H_
+#define ICN_WEB_SERVER_CONTENT_H_
+
+namespace icn_httpserver {
+
+class Content
+ : public std::istream {
+ public:
+ Content(boost::asio::streambuf &streambuf);
+
+ size_t size();
+
+ std::string string();
+
+ private:
+ boost::asio::streambuf &streambuf_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_CONTENT_H_
diff --git a/http-server/http_server.cc b/http-server/http_server.cc
new file mode 100644
index 00000000..ebc8503b
--- /dev/null
+++ b/http-server/http_server.cc
@@ -0,0 +1,487 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Ole Christian Eidheim
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#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)
+ : config_(port, num_threads),
+ icn_name_(icn_name),
+ 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) {
+}
+
+HttpServer::HttpServer(unsigned short port,
+ std::string icn_name,
+ size_t num_threads,
+ long timeout_request,
+ long timeout_send_or_receive,
+ boost::asio::io_service &ioService)
+ : config_(port, num_threads),
+ 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();
+
+ if (complete_name.getSegmentCount() <= 2) {
+ std::cerr << "Received malformed name " << complete_name << ". Ignoring it." << std::endl;
+ return;
+ }
+
+ icnet::Name request_name = complete_name.get(-1).isSegment() ? complete_name.getPrefix(-1) : complete_name;
+
+ 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;
+ std::cout << "Starting new thread" << std::endl;
+ std::thread t([this, interest, request_name, p]() {
+ processInterest(request_name, p);
+ });
+ 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();
+}
+
+void HttpServer::spawnTcpThreads() {
+ if (io_service_.stopped()) {
+ io_service_.reset();
+ }
+
+ boost::asio::ip::tcp::endpoint endpoint;
+
+ if (config_.getAddress().size() > 0) {
+ endpoint =
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(config_.getAddress()), config_.getPort());
+ } else {
+ endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), config_.getPort());
+ }
+
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(boost::asio::socket_base::reuse_address(config_.isReuse_address()));
+ acceptor_.bind(endpoint);
+ acceptor_.listen();
+
+ 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++) {
+ socket_threads_.emplace_back([this]() {
+ io_service_.run();
+ });
+ }
+}
+
+void HttpServer::start() {
+ //Copy the resources to opt_resource for more efficient request processing
+ opt_resource_.clear();
+ for (auto &res: resource) {
+ for (auto &res_method: res.second) {
+ auto it = opt_resource_.end();
+ for (auto opt_it = opt_resource_.begin(); opt_it != opt_resource_.end(); opt_it++) {
+ if (res_method.first == opt_it->first) {
+ it = opt_it;
+ break;
+ }
+ }
+ if (it == opt_resource_.end()) {
+ opt_resource_.emplace_back();
+ it = opt_resource_.begin() + (opt_resource_.size() - 1);
+ it->first = res_method.first;
+ }
+ it->second.emplace_back(boost::regex(res.first), res_method.second);
+ }
+ }
+
+ spawnTcpThreads();
+ 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();
+ // }
+}
+
+void HttpServer::stop() {
+ acceptor_.close();
+ acceptor_producer_.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_producers_) {
+ p.second.reset();
+ }
+
+}
+
+void HttpServer::accept() {
+ //Create new socket for this connection
+ //Shared_ptr is used to pass temporary objects to the asynchronous functions
+ std::shared_ptr<socket_type> socket = std::make_shared<socket_type>(io_service_);
+
+ acceptor_.async_accept(*socket, [this, socket](const boost::system::error_code &ec) {
+ //Immediately start accepting a new connection
+ accept();
+
+ if (!ec) {
+ boost::asio::ip::tcp::no_delay option(true);
+ socket->set_option(option);
+ read_request_and_content(socket);
+ }
+ });
+}
+
+void HttpServer::send(std::shared_ptr<Response> response, SendCallback callback) const {
+ response->send(callback);
+}
+
+std::shared_ptr<boost::asio::deadline_timer> HttpServer::set_timeout_on_socket(std::shared_ptr<socket_type> socket,
+ long seconds) {
+ std::shared_ptr<boost::asio::deadline_timer> timer = std::make_shared<boost::asio::deadline_timer>(io_service_);
+ timer->expires_from_now(boost::posix_time::seconds(seconds));
+ timer->async_wait([socket](const boost::system::error_code &ec) {
+ if (!ec) {
+ boost::system::error_code ec;
+ socket->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
+ socket->lowest_layer().close();
+ }
+ });
+ return timer;
+}
+
+void HttpServer::read_request_and_content(std::shared_ptr<socket_type> socket) {
+ // Create new streambuf (Request::streambuf) for async_read_until()
+ // shared_ptr is used to pass temporary objects to the asynchronous functions
+ 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
+ std::shared_ptr<boost::asio::deadline_timer> timer;
+ if (timeout_request_ > 0) {
+ timer = set_timeout_on_socket(socket, timeout_request_);
+ }
+
+ boost::asio::async_read_until(*socket,
+ request->getStreambuf(),
+ "\r\n\r\n",
+ [this, socket, request, timer](const boost::system::error_code &ec,
+ size_t bytes_transferred) {
+ if (timeout_request_ > 0) {
+ timer->cancel();
+ }
+ if (!ec) {
+ //request->streambuf.size() is not necessarily the same as bytes_transferred, from Boost-docs:
+ //"After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter"
+ //The chosen solution is to extract lines from the stream directly when parsing the header. What is left of the
+ //streambuf (maybe some bytes of the content) is appended to in the async_read-function below (for retrieving content).
+ size_t num_additional_bytes = request->getStreambuf().size() - bytes_transferred;
+
+ if (!parse_request(request, request->getContent())) {
+ return;
+ }
+
+ //If content, read that as well
+ auto it = request->getHeader().find("Content-Length");
+ if (it != request->getHeader().end()) {
+ //Set timeout on the following boost::asio::async-read or write function
+ std::shared_ptr<boost::asio::deadline_timer> timer;
+ if (timeout_content_ > 0) {
+ timer = set_timeout_on_socket(socket, timeout_content_);
+ }
+ unsigned long long content_length;
+ try {
+ content_length = stoull(it->second);
+ } catch (const std::exception &) {
+ return;
+ }
+ if (content_length > num_additional_bytes) {
+ boost::asio::async_read(*socket,
+ request->getStreambuf(),
+ boost::asio::transfer_exactly(
+ content_length - num_additional_bytes),
+ [this, socket, request, timer](const boost::system::error_code &ec,
+ size_t /*bytes_transferred*/) {
+ if (timeout_content_ > 0) {
+ timer->cancel();
+ }
+ if (!ec) {
+ find_resource(socket, request);
+ }
+ });
+ } else {
+
+ if (timeout_content_ > 0) {
+ timer->cancel();
+ }
+
+ find_resource(socket, request);
+ }
+ } else {
+ find_resource(socket, request);
+ }
+ }
+ });
+}
+
+bool HttpServer::parse_request(std::shared_ptr<Request> request, std::istream &stream) const {
+ std::string line;
+ getline(stream, line);
+ size_t method_end;
+ if ((method_end = line.find(' ')) != std::string::npos) {
+ size_t path_end;
+ if ((path_end = line.find(' ', method_end + 1)) != std::string::npos) {
+ request->setMethod(line.substr(0, method_end));
+ request->setPath(line.substr(method_end + 1, path_end - method_end - 1));
+
+ size_t protocol_end;
+ if ((protocol_end = line.find('/', path_end + 1)) != std::string::npos) {
+ if (line.substr(path_end + 1, protocol_end - path_end - 1) != "HTTP") {
+ return false;
+ }
+ request->setHttp_version(line.substr(protocol_end + 1, line.size() - protocol_end - 2));
+ } else {
+ return false;
+ }
+
+ getline(stream, line);
+ size_t param_end;
+ while ((param_end = line.find(':')) != std::string::npos) {
+ size_t value_start = param_end + 1;
+ if ((value_start) < line.size()) {
+ if (line[value_start] == ' ') {
+ value_start++;
+ }
+ if (value_start < line.size()) {
+ request->getHeader().insert(std::make_pair(line.substr(0, param_end),
+ line.substr(value_start, line.size() - value_start - 1)));
+ }
+ }
+
+ getline(stream, line);
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void HttpServer::find_resource(std::shared_ptr<socket_type> socket, std::shared_ptr<Request> request) {
+ //Find path- and method-match, and call write_response
+ for (auto &res: opt_resource_) {
+ if (request->getMethod() == res.first) {
+ for (auto &res_path: res.second) {
+ boost::smatch sm_res;
+ if (boost::regex_match(request->getPath(), sm_res, res_path.first)) {
+ request->setPath_match(std::move(sm_res));
+ write_response(socket, request, res_path.second);
+ return;
+ }
+ }
+ }
+ }
+ auto it_method = default_resource.find(request->getMethod());
+ if (it_method != default_resource.end()) {
+ write_response(socket, request, it_method->second);
+ return;
+ }
+
+ std::cout << "resource not found" << std::endl;
+}
+
+void HttpServer::write_response(std::shared_ptr<socket_type> socket,
+ std::shared_ptr<Request> request,
+ ResourceCallback &resource_function) {
+ //Set timeout on the following boost::asio::async-read or write function
+ std::shared_ptr<boost::asio::deadline_timer> timer;
+ if (timeout_content_ > 0 && socket) {
+ timer = set_timeout_on_socket(socket, timeout_content_);
+ }
+
+ Response *resp;
+
+ if (socket) {
+ resp = new SocketResponse(socket);
+ } else {
+ resp = new IcnResponse(std::static_pointer_cast<IcnRequest>(request)->getProducer(),
+ std::static_pointer_cast<IcnRequest>(request)->getName(),
+ std::static_pointer_cast<IcnRequest>(request)->getPath(),
+ std::static_pointer_cast<IcnRequest>(request)->getRequest_id());
+ }
+
+ auto response = std::shared_ptr<Response>(resp, [this, request, timer, socket](Response *response_ptr) {
+
+ auto response = std::shared_ptr<Response>(response_ptr);
+ response->setIsLast(true);
+
+ send(response, [this, response, request, timer, socket](const boost::system::error_code &ec) {
+ if (!ec) {
+ if (socket && timeout_content_ > 0) {
+ timer->cancel();
+ }
+
+ float http_version;
+ try {
+ http_version = stof(request->getHttp_version());
+ } catch (const std::exception &) {
+ return;
+ }
+
+ auto range = request->getHeader().equal_range("Connection");
+ for (auto it = range.first; it != range.second; it++) {
+ if (boost::iequals(it->second, "close")) {
+ return;
+ }
+ }
+ if (http_version > 1.05) {
+ read_request_and_content(std::static_pointer_cast<SocketResponse>(response)->getSocket());
+ }
+ }
+ });
+ });
+
+ 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
new file mode 100644
index 00000000..fbc841c7
--- /dev/null
+++ b/http-server/http_server.h
@@ -0,0 +1,125 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Ole Christian Eidheim
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef ICN_WEB_SERVER_WEB_SERVER_H_
+#define ICN_WEB_SERVER_WEB_SERVER_H_
+
+#include "common.h"
+#include "icn_request.h"
+#include "icn_response.h"
+#include "socket_request.h"
+#include "socket_response.h"
+#include "configuration.h"
+
+typedef std::function<void(std::shared_ptr<icn_httpserver::Response>, std::shared_ptr<icn_httpserver::Request>)>
+ ResourceCallback;
+
+#define SERVER_NAME "/webserver"
+#define PACKET_SIZE 1500
+#define SEND_BUFFER_SIZE 30000
+
+#define GET "GET"
+#define POST "POST"
+#define PUT "PUT"
+#define DELETE "DELETE"
+#define PATCH "PATCH"
+
+namespace icn_httpserver {
+
+class HttpServer {
+ public:
+ explicit HttpServer(unsigned short port,
+ std::string icn_name,
+ size_t num_threads,
+ long timeout_request,
+ long timeout_send_or_receive);
+
+ explicit HttpServer(unsigned short port,
+ std::string icn_name,
+ size_t num_threads,
+ long timeout_request,
+ long timeout_send_or_receive,
+ boost::asio::io_service &ioService);
+
+ void start();
+
+ void stop();
+
+ void accept();
+
+ void send(std::shared_ptr<Response> response, SendCallback callback = nullptr) const;
+
+ std::unordered_map<std::string, std::unordered_map<std::string, ResourceCallback> > resource;
+ std::unordered_map<std::string, ResourceCallback> default_resource;
+
+ private:
+ void processInterest(icnet::Name request_name, std::shared_ptr<icnet::ProducerSocket> p);
+
+ void processIncomingInterest(icnet::ProducerSocket &p, const icnet::Interest &interest);
+
+ void signPacket(icnet::ProducerSocket &p, icnet::ContentObject &content_object);
+
+ void spawnTcpThreads();
+
+ void setIcnAcceptor();
+
+ std::shared_ptr<boost::asio::deadline_timer> set_timeout_on_socket(std::shared_ptr<socket_type> socket, long seconds);
+
+ void read_request_and_content(std::shared_ptr<socket_type> socket);
+
+ bool parse_request(std::shared_ptr<Request> request, std::istream &stream) const;
+
+ void find_resource(std::shared_ptr<socket_type> socket, std::shared_ptr<Request> request);
+
+ void write_response(std::shared_ptr<socket_type> socket,
+ 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_;
+
+ std::shared_ptr<boost::asio::io_service> internal_io_service_;
+ boost::asio::io_service &io_service_;
+ boost::asio::ip::tcp::acceptor acceptor_;
+ std::vector<std::thread> socket_threads_;
+
+ // 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::mutex thread_list_mtx_;
+
+ long timeout_request_;
+ long timeout_content_;
+
+};
+
+} // end namespace icn_httpserver
+
+#endif //ICN_WEB_SERVER_WEB_SERVER_H_
diff --git a/http-server/icn_request.cc b/http-server/icn_request.cc
new file mode 100644
index 00000000..07d95a22
--- /dev/null
+++ b/http-server/icn_request.cc
@@ -0,0 +1,63 @@
+/*
+ * 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 "icn_request.h"
+
+namespace icn_httpserver {
+
+IcnRequest::IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer)
+ : producer_(producer) {
+ time_t t;
+ time(&t);
+ srand((unsigned int) t);
+ request_id_ = rand();
+}
+
+IcnRequest::IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer,
+ std::string name,
+ std::string path,
+ std::string method, std::string http_version)
+ : IcnRequest(producer) {
+ this->name_ = name;
+ this->path_ = path;
+ this->method_ = method;
+ this->http_version_ = http_version;
+}
+
+const std::string &IcnRequest::getName() const {
+ return name_;
+}
+
+void IcnRequest::setName(const std::string &name) {
+ IcnRequest::name_ = name;
+}
+
+int IcnRequest::getRequest_id() const {
+ return request_id_;
+}
+
+void IcnRequest::setRequest_id(int request_id) {
+ IcnRequest::request_id_ = request_id;
+}
+
+const std::shared_ptr<icnet::ProducerSocket> &IcnRequest::getProducer() const {
+ return producer_;
+}
+
+void IcnRequest::setProducer(const std::shared_ptr<icnet::ProducerSocket> &producer) {
+ IcnRequest::producer_ = producer;
+}
+
+} // end namespace icn_httpserver
diff --git a/http-server/icn_request.h b/http-server/icn_request.h
new file mode 100644
index 00000000..c5aa10e4
--- /dev/null
+++ b/http-server/icn_request.h
@@ -0,0 +1,56 @@
+/*
+ * 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 ICN_WEB_SERVER_ICNREQUEST_H_
+#define ICN_WEB_SERVER_ICNREQUEST_H_
+
+#include "common.h"
+#include "request.h"
+
+namespace icn_httpserver {
+
+class IcnRequest
+ : public Request {
+ public:
+ IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer);
+
+ IcnRequest(std::shared_ptr<icnet::ProducerSocket> producer,
+ std::string name,
+ std::string path,
+ std::string method,
+ std::string http_version);
+
+ const std::string &getName() const;
+
+ void setName(const std::string &name);
+
+ int getRequest_id() const;
+
+ void setRequest_id(int request_id);
+
+ const std::shared_ptr<icnet::ProducerSocket> &getProducer() const;
+
+ void setProducer(const std::shared_ptr<icnet::ProducerSocket> &producer);
+
+ private:
+ std::string name_;
+ int request_id_;
+ std::shared_ptr<icnet::ProducerSocket> producer_;
+
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_ICNREQUEST_H_
diff --git a/http-server/icn_response.cc b/http-server/icn_response.cc
new file mode 100644
index 00000000..6fe8b1e1
--- /dev/null
+++ b/http-server/icn_response.cc
@@ -0,0 +1,44 @@
+/*
+ * 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 "icn_response.h"
+
+namespace icn_httpserver {
+
+IcnResponse::IcnResponse(std::shared_ptr<icnet::ProducerSocket> producer,
+ 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) {
+}
+
+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_);
+
+ this->streambuf_.consume(buffer_size);
+
+ if (callback) {
+ callback(boost::system::error_code());
+ }
+}
+
+} // end namespace icn_httpserver
diff --git a/http-server/icn_response.h b/http-server/icn_response.h
new file mode 100644
index 00000000..e9af0d40
--- /dev/null
+++ b/http-server/icn_response.h
@@ -0,0 +1,44 @@
+/*
+ * 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 "response.h"
+
+#ifndef ICN_WEB_SERVER_ICNRESPONSE_H_
+#define ICN_WEB_SERVER_ICNRESPONSE_H_
+
+namespace icn_httpserver {
+
+class IcnResponse
+ : public Response {
+
+ public:
+
+ IcnResponse(std::shared_ptr<icnet::ProducerSocket> producer,
+ std::string ndn_name,
+ std::string ndn_path,
+ int response_id);
+
+ void send(const SendCallback &callback = nullptr);
+
+ private:
+ std::string ndn_name_;
+ std::string ndn_path_;
+ int response_id_;
+ std::shared_ptr<icnet::ProducerSocket> producer_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_ICNRESPONSE_H_
diff --git a/http-server/request.cc b/http-server/request.cc
new file mode 100644
index 00000000..0e726dc8
--- /dev/null
+++ b/http-server/request.cc
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "request.h"
+
+namespace icn_httpserver {
+
+Request::Request()
+ : content_(streambuf_) {
+}
+
+const std::string &Request::getMethod() const {
+ return method_;
+}
+
+void Request::setMethod(const std::string &method) {
+ Request::method_ = method;
+}
+
+const std::string &Request::getPath() const {
+ return path_;
+}
+
+void Request::setPath(const std::string &path) {
+ Request::path_ = path;
+}
+
+const std::string &Request::getHttp_version() const {
+ return http_version_;
+}
+
+void Request::setHttp_version(const std::string &http_version) {
+ Request::http_version_ = http_version;
+}
+
+std::unordered_multimap<std::string, std::string, ihash, iequal_to> &Request::getHeader() {
+ return header_;
+}
+
+Content &Request::getContent() {
+ return content_;
+}
+
+const boost::smatch &Request::getPath_match() const {
+ return path_match_;
+}
+
+void Request::setPath_match(const boost::smatch &path_match) {
+ Request::path_match_ = path_match;
+}
+
+} // end namespace icn_httpserver
diff --git a/http-server/request.h b/http-server/request.h
new file mode 100644
index 00000000..6ffff296
--- /dev/null
+++ b/http-server/request.h
@@ -0,0 +1,83 @@
+/*
+ * 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 ICN_WEB_SERVER_REQUEST_H_
+#define ICN_WEB_SERVER_REQUEST_H_
+
+#include "common.h"
+#include "content.h"
+
+namespace icn_httpserver {
+
+class iequal_to {
+ public:
+ bool operator()(const std::string &key1, const std::string &key2) const {
+ return boost::algorithm::iequals(key1, key2);
+ }
+};
+
+class ihash {
+ public:
+ size_t operator()(const std::string &key) const {
+ std::size_t seed = 0;
+ for (auto &c: key)
+ boost::hash_combine(seed, std::tolower(c));
+ return seed;
+ }
+};
+
+class Request {
+ public:
+
+ Request();
+
+ virtual void read_remote_endpoint_data(socket_type &socket) {
+ };
+
+ const std::string &getMethod() const;
+
+ void setMethod(const std::string &method);
+
+ const std::string &getPath() const;
+
+ void setPath(const std::string &path);
+
+ const std::string &getHttp_version() const;
+
+ void setHttp_version(const std::string &http_version);
+
+ std::unordered_multimap<std::string, std::string, ihash, iequal_to> &getHeader();
+
+ boost::asio::streambuf &getStreambuf() {
+ return streambuf_;
+ }
+
+ Content &getContent();
+
+ const boost::smatch &getPath_match() const;
+
+ void setPath_match(const boost::smatch &path_match);
+
+ protected:
+ std::string method_, path_, http_version_;
+ Content content_;
+ std::unordered_multimap<std::string, std::string, ihash, iequal_to> header_;
+ boost::smatch path_match_;
+ boost::asio::streambuf streambuf_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_REQUEST_H_
diff --git a/http-server/response.cc b/http-server/response.cc
new file mode 100644
index 00000000..b322cad8
--- /dev/null
+++ b/http-server/response.cc
@@ -0,0 +1,44 @@
+/*
+ * 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 "common.h"
+#include "response.h"
+
+namespace icn_httpserver {
+
+Response::Response()
+ : std::ostream(&streambuf_), is_last_(false) {
+}
+
+Response::~Response() {
+}
+
+std::size_t Response::size() {
+ return streambuf_.size();
+}
+
+bool Response::isIsLast() const {
+ return is_last_;
+}
+
+void Response::setIsLast(bool is_last) {
+ Response::is_last_ = is_last;
+}
+
+void Response::setResponseLength(std::size_t length) {
+ response_length_ = length;
+}
+
+} // end namespace icn_httpserver
diff --git a/http-server/response.h b/http-server/response.h
new file mode 100644
index 00000000..649bcea3
--- /dev/null
+++ b/http-server/response.h
@@ -0,0 +1,50 @@
+/*
+ * 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 ICN_WEB_SERVER_RESPONSE_H_
+#define ICN_WEB_SERVER_RESPONSE_H_
+
+#include "common.h"
+
+namespace icn_httpserver {
+
+class Response
+ : public std::ostream {
+ public:
+ Response();
+
+ virtual
+ ~Response();
+
+ size_t size();
+
+ virtual void send(const SendCallback &callback = nullptr) {
+ };
+
+ bool isIsLast() const;
+
+ void setIsLast(bool is_last);
+
+ void setResponseLength(std::size_t length);
+
+ protected:
+ boost::asio::streambuf streambuf_;
+ bool is_last_;
+ std::size_t response_length_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_RESPONSE_H_
diff --git a/http-server/socket_request.cc b/http-server/socket_request.cc
new file mode 100644
index 00000000..10c663a5
--- /dev/null
+++ b/http-server/socket_request.cc
@@ -0,0 +1,37 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Ole Christian Eidheim
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "socket_request.h"
+
+namespace icn_httpserver {
+
+void SocketRequest::read_remote_endpoint_data(socket_type &socket) {
+ try {
+ remote_endpoint_address_ = socket.lowest_layer().remote_endpoint().address().to_string();
+ remote_endpoint_port_ = socket.lowest_layer().remote_endpoint().port();
+ } catch (const std::exception &) {
+ }
+}
+
+} // end namespace icn_httpserver
diff --git a/http-server/socket_request.h b/http-server/socket_request.h
new file mode 100644
index 00000000..cc77ef73
--- /dev/null
+++ b/http-server/socket_request.h
@@ -0,0 +1,44 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Ole Christian Eidheim
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef ICN_WEB_SERVER_SOCKETREQUEST_H_
+#define ICN_WEB_SERVER_SOCKETREQUEST_H_
+
+#include "request.h"
+
+namespace icn_httpserver {
+
+class SocketRequest
+ : public Request {
+ public:
+ void read_remote_endpoint_data(socket_type &socket);
+
+ private:
+ std::string remote_endpoint_address_;
+ unsigned short remote_endpoint_port_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_SOCKETREQUEST_H_
diff --git a/http-server/socket_response.cc b/http-server/socket_response.cc
new file mode 100644
index 00000000..ec33820e
--- /dev/null
+++ b/http-server/socket_response.cc
@@ -0,0 +1,54 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Ole Christian Eidheim
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "socket_response.h"
+
+namespace icn_httpserver {
+
+SocketResponse::SocketResponse(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
+ : socket_(socket) {
+}
+
+SocketResponse::~SocketResponse() {
+};
+
+void SocketResponse::send(const SendCallback &callback) {
+ boost::asio::async_write(*this->socket_,
+ this->streambuf_,
+ [this, callback](const boost::system::error_code &ec, size_t /*bytes_transferred*/) {
+ if (callback) {
+ callback(ec);
+ }
+ });
+}
+
+const std::shared_ptr<socket_type> &SocketResponse::getSocket() const {
+ return socket_;
+}
+
+void SocketResponse::setSocket(const std::shared_ptr<socket_type> &socket) {
+ SocketResponse::socket_ = socket;
+}
+
+} // end namespace icn_httpserver
diff --git a/http-server/socket_response.h b/http-server/socket_response.h
new file mode 100644
index 00000000..722e8196
--- /dev/null
+++ b/http-server/socket_response.h
@@ -0,0 +1,52 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2016 Ole Christian Eidheim
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef ICN_WEB_SERVER_SOCKETRESPONSE_H_
+#define ICN_WEB_SERVER_SOCKETRESPONSE_H_
+
+#include "response.h"
+
+namespace icn_httpserver {
+
+class SocketResponse
+ : public Response {
+ public:
+
+ SocketResponse(std::shared_ptr<socket_type> socket);
+
+ ~SocketResponse();
+
+ void send(const SendCallback &callback = nullptr);
+
+ const std::shared_ptr<socket_type> &getSocket() const;
+
+ void setSocket(const std::shared_ptr<socket_type> &socket);
+
+ private:
+ std::shared_ptr<socket_type> socket_;
+};
+
+} // end namespace icn_httpserver
+
+#endif // ICN_WEB_SERVER_SOCKETRESPONSE_H_