summaryrefslogtreecommitdiffstats
path: root/apps/src
diff options
context:
space:
mode:
authorAngelo Mantellini <manangel@cisco.com>2019-03-15 14:16:15 +0100
committerAngelo Mantellini <manangel@cisco.com>2019-03-15 17:38:46 +0100
commita1e949253043fe1a644f71cef0572ede30b752be (patch)
tree6cbe2288a82942014edb074d9b194771446b29b7 /apps/src
parente1033d6fac2ad70891a96695284b2c1e7013c91c (diff)
[HICN-114] Update Hicn Http Server to hicn fdio stack
Change-Id: Ic808c93c14f905fd403e60be82ce319757e84c9f Signed-off-by: Angelo Mantellini <manangel@cisco.com>
Diffstat (limited to 'apps/src')
-rw-r--r--apps/src/higet/CMakeLists.txt41
-rw-r--r--[-rwxr-xr-x]apps/src/higet/higet.cc (renamed from apps/src/higet.cc)71
-rw-r--r--apps/src/http-server/CMakeLists.txt79
-rw-r--r--apps/src/http-server/config.h.in19
-rw-r--r--apps/src/http-server/http-client/http_client.h37
-rw-r--r--apps/src/http-server/http-client/http_client_icn.cc37
-rw-r--r--apps/src/http-server/http-client/http_client_icn.h34
-rw-r--r--apps/src/http-server/http-client/http_client_tcp.cc99
-rw-r--r--apps/src/http-server/http-client/http_client_tcp.h36
-rw-r--r--apps/src/http-server/http-server.cc343
-rw-r--r--apps/src/http-server/http-server/common.h43
-rw-r--r--apps/src/http-server/http-server/configuration.cc47
-rw-r--r--apps/src/http-server/http-server/configuration.h49
-rw-r--r--apps/src/http-server/http-server/content.cc31
-rw-r--r--apps/src/http-server/http-server/content.h34
-rw-r--r--apps/src/http-server/http-server/http_server.cc416
-rw-r--r--apps/src/http-server/http-server/http_server.h118
-rw-r--r--apps/src/http-server/http-server/icn_request.cc60
-rw-r--r--apps/src/http-server/http-server/icn_request.h53
-rw-r--r--apps/src/http-server/http-server/icn_response.cc49
-rw-r--r--apps/src/http-server/http-server/icn_response.h39
-rw-r--r--apps/src/http-server/http-server/request.cc71
-rw-r--r--apps/src/http-server/http-server/request.h91
-rw-r--r--apps/src/http-server/http-server/response.cc48
-rw-r--r--apps/src/http-server/http-server/response.h50
-rw-r--r--apps/src/http-server/http-server/socket_request.cc38
-rw-r--r--apps/src/http-server/http-server/socket_request.h40
-rw-r--r--apps/src/http-server/http-server/socket_response.cc52
-rw-r--r--apps/src/http-server/http-server/socket_response.h47
29 files changed, 2139 insertions, 33 deletions
diff --git a/apps/src/higet/CMakeLists.txt b/apps/src/higet/CMakeLists.txt
new file mode 100644
index 000000000..a144d4c08
--- /dev/null
+++ b/apps/src/higet/CMakeLists.txt
@@ -0,0 +1,41 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+set(CMAKE_CXX_STANDARD 14)
+
+project(utils)
+
+set(CMAKE_MODULE_PATH
+ ${CMAKE_MODULE_PATH}
+ "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules"
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+)
+
+list(APPEND APPS_SRC
+ higet.cc
+)
+
+
+foreach(app ${APPS_SRC})
+ get_filename_component(_app_name ${app} NAME)
+ string(REGEX REPLACE ".cc" "" app_name ${_app_name})
+
+ build_executable(${app_name}
+ SOURCES ${app}
+ LINK_LIBRARIES ${LIBTRANSPORT_LIBRARIES} ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+ DEPENDS ${LIBTRANSPORT}
+ COMPONENT ${HICN_APPS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ )
+endforeach()
diff --git a/apps/src/higet.cc b/apps/src/higet/higet.cc
index d2ef818cb..58b582a9d 100755..100644
--- a/apps/src/higet.cc
+++ b/apps/src/higet/higet.cc
@@ -35,12 +35,14 @@ typedef struct {
std::string producer_certificate;
} Configuration;
-void processResponse(Configuration &conf, transport::http::HTTPResponse &&response) {
+void processResponse(Configuration &conf,
+ transport::http::HTTPResponse &&response) {
auto &payload = response.getPayload();
if (conf.file_name != "-") {
- std::cerr << "Saving to: " << conf.file_name << " " << payload.size() << "kB" << std::endl;
+ std::cerr << "Saving to: " << conf.file_name << " " << payload.size()
+ << "kB" << std::endl;
}
Time t3 = std::chrono::system_clock::now();
@@ -59,7 +61,8 @@ void processResponse(Configuration &conf, transport::http::HTTPResponse &&respon
if (conf.print_headers) {
auto &headers = response.getHeaders();
- out << "HTTP/" << response.getHttpVersion() << " " << response.getStatusCode() << " " << response.getStatusString()
+ out << "HTTP/" << response.getHttpVersion() << " "
+ << response.getStatusCode() << " " << response.getStatusString()
<< "\n";
for (auto &h : headers) {
out << h.first << ": " << h.second << "\n";
@@ -70,31 +73,37 @@ void processResponse(Configuration &conf, transport::http::HTTPResponse &&respon
out.write((char *)payload.data(), payload.size());
of.close();
- Time t2 = std::chrono::system_clock::now();;
- TimeDuration dt = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
- TimeDuration dt3 = std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t1);
+ Time t2 = std::chrono::system_clock::now();
+ ;
+ TimeDuration dt =
+ std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
+ TimeDuration dt3 =
+ std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t1);
long msec = (long)dt.count();
long msec3 = (long)dt3.count();
- std::cerr << "Elapsed Time: " << msec / 1000.0 << " seconds -- " << payload.size() * 8 / msec / 1000.0
- << "[Mbps] -- " << payload.size() * 8 / msec3 / 1000.0 << "[Mbps]" << std::endl;
-
+ std::cerr << "Elapsed Time: " << msec / 1000.0 << " seconds -- "
+ << payload.size() * 8 / msec / 1000.0 << "[Mbps] -- "
+ << payload.size() * 8 / msec3 / 1000.0 << "[Mbps]" << std::endl;
}
void usage(char *program_name) {
std::cerr << "USAGE:" << std::endl;
std::cerr << "\t" << program_name << " [OPTION]... [URL]..." << std::endl;
std::cerr << "OPTIONS:" << std::endl;
- std::cerr << "\t" << "-O filename write documents to FILE" << std::endl;
- std::cerr << "\t" << "-S print server response" << std::endl;
+ std::cerr << "\t"
+ << "-O filename write documents to FILE" << std::endl;
+ std::cerr << "\t"
+ << "-S print server response" << std::endl;
std::cerr << "EXAMPLE:" << std::endl;
- std::cerr << "\t" << program_name << " -O - http://origin/index.html" << std::endl;
+ std::cerr << "\t" << program_name << " -O - http://origin/index.html"
+ << std::endl;
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
#ifdef _WIN32
- WSADATA wsaData = { 0 };
+ WSADATA wsaData = {0};
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
@@ -108,19 +117,19 @@ int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "O:Sc:")) != -1) {
switch (opt) {
- case 'O':
- conf.file_name = optarg;
- break;
- case 'S':
- conf.print_headers = true;
- break;
- case 'c':
- conf.producer_certificate = optarg;
- break;
- case 'h':
- default:
- usage(argv[0]);
- break;
+ case 'O':
+ conf.file_name = optarg;
+ break;
+ case 'S':
+ conf.print_headers = true;
+ break;
+ case 'c':
+ conf.producer_certificate = optarg;
+ break;
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
}
}
@@ -134,10 +143,8 @@ int main(int argc, char **argv) {
conf.file_name = name.substr(1 + name.find_last_of("/"));
}
- std::map<std::string, std::string> headers = {
- {"Host", "localhost"},
- {"User-Agent", "higet/1.0"}
- };
+ std::map<std::string, std::string> headers = {{"Host", "localhost"},
+ {"User-Agent", "higet/1.0"}};
transport::http::HTTPClientConnection connection;
if (!conf.producer_certificate.empty()) {
@@ -160,6 +167,4 @@ int main(int argc, char **argv) {
} // end namespace hicnet
-int main(int argc, char **argv) {
- return hicnet::http::main(argc, argv);
-}
+int main(int argc, char **argv) { return hicnet::http::main(argc, argv); }
diff --git a/apps/src/http-server/CMakeLists.txt b/apps/src/http-server/CMakeLists.txt
new file mode 100644
index 000000000..a005f1a8f
--- /dev/null
+++ b/apps/src/http-server/CMakeLists.txt
@@ -0,0 +1,79 @@
+# 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.
+
+cmake_minimum_required(VERSION 3.2)
+
+set(CMAKE_CXX_STANDARD 14)
+
+option(HICNET "Link against Libhicnet." ON)
+
+configure_file("${PROJECT_SOURCE_DIR}/src/http-server/config.h.in"
+ "${CMAKE_BINARY_DIR}/apps/http-server/config.h")
+
+set(LIB_SOURCE_FILES
+ http-server/http_server.cc
+ http-server/response.cc
+ http-server/socket_response.cc
+ http-server/icn_response.cc
+ http-server/content.cc
+ http-server/request.cc
+ http-server/icn_request.cc
+ http-server/socket_request.cc
+ 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
+ ${CMAKE_BINARY_DIR}/apps/http-server/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
+ http-server.cc)
+
+include_directories(${CMAKE_BINARY_DIR}/apps/http-server http-server http-client)
+
+build_library(hicn-httpserver
+ STATIC
+ SOURCES ${LIB_SOURCE_FILES} ${LIB_SERVER_HEADER_FILES} ${LIB_CLIENT_HEADER_FILES}
+ INSTALL_HEADERS ${HEADER_FILES}
+ LINK_LIBRARIES ${LIBRARIES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT lib${LIBTRANSPORT}
+ INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS}
+ INSTALL_ROOT_DIR hicn/transport
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+)
+
+
+build_executable(hicn-http-server
+ SOURCES ${APP_SOURCE_FILES}
+ LINK_LIBRARIES hicn-httpserver ${WSOCK32_LIBRARY} ${WS2_32_LIBRARY}
+ DEPENDS hicn-httpserver
+ COMPONENT ${HICN_APPS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+)
+
diff --git a/apps/src/http-server/config.h.in b/apps/src/http-server/config.h.in
new file mode 100644
index 000000000..d10e62ee2
--- /dev/null
+++ b/apps/src/http-server/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/apps/src/http-server/http-client/http_client.h b/apps/src/http-server/http-client/http_client.h
new file mode 100644
index 000000000..b2dbd1ffd
--- /dev/null
+++ b/apps/src/http-server/http-client/http_client.h
@@ -0,0 +1,37 @@
+/*
+ * 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 "config.h"
+
+#include <string>
+
+#if defined(HICNET)
+#include <hicn/transport/http/facade.h>
+#elif defined(ICNET)
+#include <icnet/icnet_http_facade.h>
+#else
+#error "No ICN tranport library to which link against."
+#endif
+
+class HTTPClient {
+public:
+ virtual ~HTTPClient() = default;
+
+ virtual void setTcp() = 0;
+
+ virtual bool download(const std::string &url, std::ostream &out) = 0;
+};
diff --git a/apps/src/http-server/http-client/http_client_icn.cc b/apps/src/http-server/http-client/http_client_icn.cc
new file mode 100644
index 000000000..862741bd9
--- /dev/null
+++ b/apps/src/http-server/http-client/http_client_icn.cc
@@ -0,0 +1,37 @@
+/*
+ * 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 <curl/curl.h>
+
+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<const char *>(r.data()), r.size());
+ return true;
+}
diff --git a/apps/src/http-server/http-client/http_client_icn.h b/apps/src/http-server/http-client/http_client_icn.h
new file mode 100644
index 000000000..8f5e9ae44
--- /dev/null
+++ b/apps/src/http-server/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 <string>
+
+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/apps/src/http-server/http-client/http_client_tcp.cc b/apps/src/http-server/http-client/http_client_tcp.cc
new file mode 100644
index 000000000..08474d71c
--- /dev/null
+++ b/apps/src/http-server/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 <curl/curl.h>
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <string.h>
+
+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->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/apps/src/http-server/http-client/http_client_tcp.h b/apps/src/http-server/http-client/http_client_tcp.h
new file mode 100644
index 000000000..e1d81ada0
--- /dev/null
+++ b/apps/src/http-server/http-client/http_client_tcp.h
@@ -0,0 +1,36 @@
+/*
+ * 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 <string>
+
+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/apps/src/http-server/http-server.cc b/apps/src/http-server/http-server.cc
new file mode 100644
index 000000000..7f6f8a3e8
--- /dev/null
+++ b/apps/src/http-server/http-server.cc
@@ -0,0 +1,343 @@
+/*
+ * 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 <fstream>
+#include <iostream>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "http-server/http_server.h"
+#include "http_client_icn.h"
+#include "http_client_tcp.h"
+
+typedef icn_httpserver::HttpServer HttpServer;
+typedef icn_httpserver::Response Response;
+typedef icn_httpserver::Request Request;
+
+namespace std {
+
+string getFileName(const string &strPath) {
+ size_t iLastSeparator = 0;
+#ifdef _WIN32
+ return strPath.substr((iLastSeparator = strPath.find_last_of("\\")) !=
+ std::string::npos
+ ? iLastSeparator + 1
+ : 0,
+ strPath.size() - strPath.find_last_of("."));
+#else
+ return strPath.substr((iLastSeparator = strPath.find_last_of("/")) !=
+ std::string::npos
+ ? iLastSeparator + 1
+ : 0,
+ strPath.size() - strPath.find_last_of("."));
+#endif
+}
+
+string getExtension(const string &strPath) {
+ size_t iLastSeparator = 0;
+ return strPath.substr((iLastSeparator = strPath.find_last_of(".")) !=
+ std::string::npos
+ ? iLastSeparator + 1
+ : 0,
+ strPath.size());
+}
+
+int isRegularFile(const string path) {
+ struct stat path_stat;
+ stat(path.c_str(), &path_stat);
+ return S_ISREG(path_stat.st_mode);
+}
+
+int isDirectory(const string path) {
+ struct stat statbuf;
+ if (stat(path.c_str(), &statbuf) != 0)
+ return 0;
+ return S_ISDIR(statbuf.st_mode);
+}
+
+void default_resource_send(const HttpServer &server,
+ shared_ptr<Response> response,
+ shared_ptr<ifstream> ifs,
+ shared_ptr<vector<char>> buffer,
+ std::size_t bytes_to_read) {
+ streamsize read_length;
+
+ if ((read_length = ifs->read(&(*buffer)[0], buffer->size()).gcount()) > 0) {
+ response->write(&(*buffer)[0], read_length);
+
+ if (bytes_to_read <= static_cast<std::size_t>(buffer->size())) {
+ // If this is the last part of the response, send it at the pointer
+ // deletion!
+ return;
+ }
+
+ std::size_t to_read = bytes_to_read - read_length;
+ server.send(response, [&server, response, ifs, buffer,
+ to_read](const std::error_code &ec) {
+ if (!ec) {
+ default_resource_send(server, response, ifs, buffer, to_read);
+ } else {
+ cerr << "Connection interrupted" << endl;
+ }
+ });
+ }
+}
+
+void afterSignal(HttpServer *webServer, const std::error_code &errorCode) {
+ cout << "\nGracefully terminating http-server... wait." << endl;
+ webServer->stop();
+}
+
+void usage(const char *programName) {
+ cerr << programName
+ << " [-p PATH_TO_ROOT_FOOT_FOLDER] [-f CONFIGURATION_FILE] [-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);
+}
+
+int main(int argc, char **argv) {
+ // Parse command line arguments
+
+ string root_folder = "/var/www/html";
+ string webserver_prefix = "http://webserver";
+ string tcp_proxy_address;
+ string icn_proxy_prefix;
+ int port = 8080;
+ int opt = 0;
+
+ while ((opt = getopt(argc, argv, "p:l:o:hx:z:")) != -1) {
+ switch (opt) {
+ case 'p':
+ root_folder = optarg;
+ break;
+ case 'l':
+ webserver_prefix = optarg;
+ break;
+ case 'x':
+ tcp_proxy_address = optarg;
+ break;
+ case 'o':
+ port = atoi(optarg);
+ break;
+ case 'z':
+ icn_proxy_prefix = optarg;
+ break;
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ if (!(std::ifstream(root_folder).good())) {
+ if (mkdir(root_folder.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) ==
+ -1) {
+ std::cerr << "The web root folder " << root_folder
+ << " does not exist and its creation failed. Exiting.."
+ << std::endl;
+ return (EXIT_FAILURE);
+ }
+ }
+
+ 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;
+ }
+
+ asio::io_service io_service;
+ HttpServer server(port, webserver_prefix, 50, 5, 300, io_service);
+
+ // GET for the path /info
+ // Responds with some server info
+ server.resource["^/info$"]["GET"] = [](shared_ptr<Response> response,
+ shared_ptr<Request> request) {
+ stringstream content_stream;
+ content_stream
+ << "<h1>This webserver is able to reply to HTTP over TCP/ICN</h1>";
+ content_stream << request->getMethod() << " " << request->getPath()
+ << " HTTP/" << request->getHttp_version() << "<br>";
+
+ for (auto &header : request->getHeader()) {
+ content_stream << header.first << ": " << header.second << "<br>";
+ }
+
+ // find length of content_stream (length received using
+ // content_stream.tellp())
+ content_stream.seekp(0, ios::end);
+
+ *response << "HTTP/1.1 200 OK\r\nContent-Length: " << content_stream.tellp()
+ << "\r\n\r\n"
+ << content_stream.rdbuf();
+ };
+
+ // Default GET-example. If no other matches, this anonymous function will be
+ // called. 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, &tcp_proxy_address, &icn_proxy_prefix](
+ shared_ptr<Response> response, shared_ptr<Request> request) {
+ const auto web_root_path = root_folder;
+ std::string path = web_root_path;
+
+ // check if there is "/"
+ path = path + request->getPath();
+ std::cout << "path:" << path << std::endl;
+ auto socket_request =
+ dynamic_cast<icn_httpserver::SocketRequest *>(request.get());
+
+ std::chrono::milliseconds response_lifetime;
+ std::string stem = getFileName(path);
+ std::string extension = getExtension(path);
+ if (extension == "mpd" || stem == "latest") {
+ std::cout << "1 second" << std::endl;
+ std::cout << "Setting lifetime to 1 second" << std::endl;
+ response_lifetime = std::chrono::milliseconds(1000);
+ } else {
+ std::cout << "5 second" << std::endl;
+ std::cout << "Setting lifetime to 5 second" << std::endl;
+ response_lifetime = std::chrono::milliseconds(5000);
+ }
+
+ response->setResponseLifetime(response_lifetime);
+
+ if (std::ifstream(path).good()) {
+
+ // Check if path is within web_root_path
+ if (distance(web_root_path.begin(), web_root_path.end()) <=
+ distance(path.begin(), path.end()) &&
+ equal(web_root_path.begin(), web_root_path.end(), path.begin())) {
+ if (isDirectory(path)) {
+ path += "index.html";
+ } // default path
+
+ if (std::ifstream(path).good() && isRegularFile(path)) {
+
+ auto ifs = make_shared<ifstream>();
+ ifs->open(path, ifstream::in | ios::binary);
+
+ if (*ifs) {
+ // read and send 15 MB at a time
+ streamsize buffer_size = 15 * 1024 * 1024;
+ auto buffer = make_shared<vector<char>>(buffer_size);
+
+ ifs->seekg(0, ios::end);
+ auto length = ifs->tellg();
+ ifs->seekg(0, ios::beg);
+
+ response->setResponseLength(length);
+ *response << "HTTP/1.0 200 OK\r\nContent-Length: " << length
+ << "\r\n\r\n";
+
+ default_resource_send(server, response, ifs, buffer, length);
+
+ return;
+ }
+ }
+ }
+ }
+
+ 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.c_str(), 7) != 0) {
+ if (strncmp("https://", proxy.c_str(), 8) != 0) {
+ ss << "https://";
+ } else {
+ ss << "http://";
+ }
+ }
+
+ ss << proxy;
+ ss << request->getPath();
+
+ std::cout << "Forwarding request to " << ss.str() << std::endl;
+
+ client->download(ss.str(), *response);
+
+ delete client;
+
+ if (response->size() == 0) {
+ *response << "HTTP/1.1 504 Gateway Timeout\r\n\r\n";
+ }
+
+ return;
+ }
+
+ 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;
+ };
+
+ // Let the main thread to catch SIGINT and SIGQUIT
+ asio::signal_set signals(io_service, SIGINT, SIGQUIT);
+ signals.async_wait(bind(afterSignal, &server, placeholders::_1));
+
+ thread server_thread([&server]() {
+ // Start server
+ server.start();
+ });
+
+ if (server_thread.joinable()) {
+ server_thread.join();
+ }
+
+ return 0;
+}
+
+} // end namespace std
+
+int main(int argc, char **argv) { return std::main(argc, argv); }
diff --git a/apps/src/http-server/http-server/common.h b/apps/src/http-server/http-server/common.h
new file mode 100644
index 000000000..81f6757c7
--- /dev/null
+++ b/apps/src/http-server/http-server/common.h
@@ -0,0 +1,43 @@
+/*
+ * 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 "config.h"
+
+#if defined(HICNET)
+#include <hicn/transport/http/facade.h>
+#include <hicn/transport/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 <algorithm>
+#include <asio.hpp>
+#include <functional>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <regex>
+#include <sstream>
+#include <string>
+#include <thread>
+#include <unordered_map>
+
+typedef asio::ip::tcp::socket socket_type;
+typedef std::function<void(const std::error_code &)> SendCallback;
diff --git a/apps/src/http-server/http-server/configuration.cc b/apps/src/http-server/http-server/configuration.cc
new file mode 100644
index 000000000..603396b44
--- /dev/null
+++ b/apps/src/http-server/http-server/configuration.cc
@@ -0,0 +1,47 @@
+/*
+ * 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/apps/src/http-server/http-server/configuration.h b/apps/src/http-server/http-server/configuration.h
new file mode 100644
index 000000000..b87558f91
--- /dev/null
+++ b/apps/src/http-server/http-server/configuration.h
@@ -0,0 +1,49 @@
+/*
+ * 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 "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
diff --git a/apps/src/http-server/http-server/content.cc b/apps/src/http-server/http-server/content.cc
new file mode 100644
index 000000000..8ad16f904
--- /dev/null
+++ b/apps/src/http-server/http-server/content.cc
@@ -0,0 +1,31 @@
+/*
+ * 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(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/apps/src/http-server/http-server/content.h b/apps/src/http-server/http-server/content.h
new file mode 100644
index 000000000..ebf2f7f32
--- /dev/null
+++ b/apps/src/http-server/http-server/content.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.
+ */
+
+#include "common.h"
+
+#pragma once
+
+namespace icn_httpserver {
+
+class Content : public std::istream {
+public:
+ Content(asio::streambuf &streambuf);
+
+ size_t size();
+
+ std::string string();
+
+private:
+ asio::streambuf &streambuf_;
+};
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/http_server.cc b/apps/src/http-server/http-server/http_server.cc
new file mode 100644
index 000000000..911656f7a
--- /dev/null
+++ b/apps/src/http-server/http-server/http_server.cc
@@ -0,0 +1,416 @@
+/*
+ * 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"
+
+#include <asio.hpp>
+#include <fstream>
+#include <istream>
+
+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),
+ internal_io_service_(std::make_shared<asio::io_service>()),
+ io_service_(*internal_io_service_), acceptor_(io_service_),
+ icn_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,
+ asio::io_service &ioService)
+ : config_(port, num_threads), io_service_(ioService),
+ acceptor_(io_service_), icn_name_(icn_name),
+ timeout_request_(timeout_request),
+ timeout_content_(timeout_send_or_receive) {}
+
+void HttpServer::onIcnRequest(
+ std::shared_ptr<libl4::http::HTTPServerPublisher> &publisher,
+ const uint8_t *buffer, std::size_t size, int request_id) {
+ std::shared_ptr<Request> request = std::make_shared<IcnRequest>(publisher);
+ request->getContent().rdbuf()->sputn((char *)buffer, size);
+
+ if (!parse_request(request, request->getContent())) {
+ return;
+ }
+
+ std::map<int, std::shared_ptr<libl4::http::HTTPServerPublisher>>
+ &icn_publishers = icn_acceptor_->getPublishers();
+
+ std::unique_lock<std::mutex> lock(thread_list_mtx_);
+ if (icn_publishers.size() < config_.getNum_threads()) {
+ std::cout << "Received request for: " << request->getPath() << std::endl;
+
+ publisher->attachPublisher();
+ std::cout << "Starting new thread" << std::endl;
+ io_service_.dispatch([this, request, request_id]() {
+ std::map<int, std::shared_ptr<libl4::http::HTTPServerPublisher>>
+ &icn_publishers = icn_acceptor_->getPublishers();
+ find_resource(nullptr, request);
+ icn_publishers[request_id]->serveClients();
+ std::unique_lock<std::mutex> lock(thread_list_mtx_);
+ icn_publishers.erase(request_id);
+ });
+ }
+}
+
+void HttpServer::setIcnAcceptor() {
+ icn_acceptor_ = std::make_shared<libl4::http::HTTPServerAcceptor>(
+ icn_name_, std::bind(&HttpServer::onIcnRequest, this,
+ std::placeholders::_1, std::placeholders::_2,
+ std::placeholders::_3, std::placeholders::_4));
+ icn_acceptor_->listen(true);
+}
+
+void HttpServer::spawnThreads() {
+ if (io_service_.stopped()) {
+ io_service_.reset();
+ }
+
+ asio::ip::tcp::endpoint endpoint;
+
+ if (config_.getAddress().size() > 0) {
+ endpoint = asio::ip::tcp::endpoint(
+ asio::ip::address::from_string(config_.getAddress()),
+ config_.getPort());
+ } else {
+ endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v4(), config_.getPort());
+ }
+
+ acceptor_.open(endpoint.protocol());
+ acceptor_.set_option(
+ 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(std::regex(res.first), res_method.second);
+ }
+ }
+
+ 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();
+ // }
+}
+
+void HttpServer::stop() {
+ acceptor_.close();
+
+ io_service_.stop();
+
+ std::map<int, std::shared_ptr<libl4::http::HTTPServerPublisher>>
+ &icn_publishers = icn_acceptor_->getPublishers();
+
+ for (auto &p : icn_publishers) {
+ p.second->stop();
+ }
+}
+
+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 std::error_code &ec) {
+ // Immediately start accepting a new connection
+ accept();
+
+ if (!ec) {
+ 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<asio::steady_timer>
+HttpServer::set_timeout_on_socket(std::shared_ptr<socket_type> socket,
+ long seconds) {
+ std::shared_ptr<asio::steady_timer> timer =
+ std::make_shared<asio::steady_timer>(io_service_);
+ timer->expires_from_now(std::chrono::seconds(seconds));
+ timer->async_wait([socket](const std::error_code &ec) {
+ if (!ec) {
+ std::error_code ec;
+ socket->lowest_layer().shutdown(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 asio::async-read or write function
+ std::shared_ptr<asio::steady_timer> timer;
+ if (timeout_request_ > 0) {
+ timer = set_timeout_on_socket(socket, timeout_request_);
+ }
+
+ asio::async_read_until(
+ *socket, request->getStreambuf(), "\r\n\r\n",
+ [this, socket, request, timer](const std::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 Asio-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().in_avail() - 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 asio::async-read or write function
+ std::shared_ptr<asio::steady_timer> timer;
+ if (timeout_content_ > 0) {
+ timer = set_timeout_on_socket(socket, timeout_content_);
+ }
+ unsigned long long content_length;
+ try {
+ content_length = atol(it->second.c_str());
+ } catch (const std::exception &) {
+ return;
+ }
+ if (content_length > num_additional_bytes) {
+ asio::async_read(
+ *socket, request->getStreambuf(),
+ asio::transfer_exactly(content_length - num_additional_bytes),
+ [this, socket, request, timer](const std::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) {
+ std::smatch sm_res;
+ if (std::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 asio::async-read or write function
+ std::shared_ptr<asio::steady_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)->getHttpPublisher(),
+ std::static_pointer_cast<IcnRequest>(request)->getName(),
+ std::static_pointer_cast<IcnRequest>(request)->getPath());
+ }
+
+ 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 std::error_code &ec) {
+ if (!ec) {
+ if (socket && timeout_content_ > 0) {
+ timer->cancel();
+ }
+
+ float http_version;
+ try {
+ http_version = atof(request->getHttp_version().c_str());
+ } catch (const std::exception &) {
+ return;
+ }
+
+ auto range = request->getHeader().equal_range("Connection");
+ for (auto it = range.first; it != range.second; it++) {
+ if (caseInsCompare(it->second, "close")) {
+ return;
+ }
+ }
+ if (http_version > 1.05 && socket) {
+ 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/apps/src/http-server/http-server/http_server.h b/apps/src/http-server/http-server/http_server.h
new file mode 100644
index 000000000..3468b438a
--- /dev/null
+++ b/apps/src/http-server/http-server/http_server.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "common.h"
+#include "configuration.h"
+#include "icn_request.h"
+#include "icn_response.h"
+#include "socket_request.h"
+#include "socket_response.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,
+ 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;
+
+ void
+ onIcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher> &publisher,
+ const uint8_t *buffer, std::size_t size, int request_id);
+
+private:
+ void spawnThreads();
+
+ void setIcnAcceptor();
+
+ std::shared_ptr<asio::steady_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);
+
+ Configuration config_;
+
+ std::vector<std::pair<std::string,
+ std::vector<std::pair<std::regex, ResourceCallback>>>>
+ opt_resource_;
+
+ std::shared_ptr<asio::io_service> internal_io_service_;
+ asio::io_service &io_service_;
+ asio::ip::tcp::acceptor acceptor_;
+ std::vector<std::thread> socket_threads_;
+ std::string icn_name_;
+ std::shared_ptr<libl4::http::HTTPServerAcceptor> icn_acceptor_;
+ std::mutex thread_list_mtx_;
+
+ long timeout_request_;
+ long timeout_content_;
+};
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/icn_request.cc b/apps/src/http-server/http-server/icn_request.cc
new file mode 100644
index 000000000..7871d908d
--- /dev/null
+++ b/apps/src/http-server/http-server/icn_request.cc
@@ -0,0 +1,60 @@
+/*
+ * 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<libl4::http::HTTPServerPublisher> &publisher)
+ : publisher_(publisher) {
+ time_t t;
+ time(&t);
+ srand((unsigned int)t);
+ request_id_ = rand();
+}
+
+IcnRequest::IcnRequest(
+ std::shared_ptr<libl4::http::HTTPServerPublisher> &publisher,
+ std::string name, std::string path, std::string method,
+ std::string http_version)
+ : IcnRequest(publisher) {
+ 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<libl4::http::HTTPServerPublisher> &
+IcnRequest::getHttpPublisher() const {
+ return publisher_;
+}
+
+void IcnRequest::setProducer(
+ const std::shared_ptr<libl4::http::HTTPServerPublisher> &producer) {
+ IcnRequest::publisher_ = producer;
+}
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/icn_request.h b/apps/src/http-server/http-server/icn_request.h
new file mode 100644
index 000000000..adf36d129
--- /dev/null
+++ b/apps/src/http-server/http-server/icn_request.h
@@ -0,0 +1,53 @@
+/*
+ * 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 "common.h"
+#include "request.h"
+
+namespace icn_httpserver {
+
+class IcnRequest : public Request {
+public:
+ IcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher> &publisher);
+
+ IcnRequest(std::shared_ptr<libl4::http::HTTPServerPublisher> &publisher,
+ std::string name, std::string path, std::string method,
+ std::string http_version);
+
+ ~IcnRequest() = default;
+
+ 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<libl4::http::HTTPServerPublisher> &
+ getHttpPublisher() const;
+
+ void setProducer(
+ const std::shared_ptr<libl4::http::HTTPServerPublisher> &producer);
+
+private:
+ std::string name_;
+ int request_id_;
+ std::shared_ptr<libl4::http::HTTPServerPublisher> publisher_;
+};
+
+} // end namespace icn_httpserver \ No newline at end of file
diff --git a/apps/src/http-server/http-server/icn_response.cc b/apps/src/http-server/http-server/icn_response.cc
new file mode 100644
index 000000000..11d0faf6b
--- /dev/null
+++ b/apps/src/http-server/http-server/icn_response.cc
@@ -0,0 +1,49 @@
+/*
+ * 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<libl4::http::HTTPServerPublisher> publisher,
+ std::string ndn_name,
+ std::string ndn_path) //,
+ // int response_id)
+ : ndn_name_(ndn_name), ndn_path_(ndn_path), publisher_(publisher) {}
+
+void IcnResponse::send(const SendCallback &callback) {
+
+ std::size_t buffer_size = this->streambuf_.size();
+ this->streambuf_.commit(this->streambuf_.size());
+
+ this->publisher_->publishContent(
+ asio::buffer_cast<const uint8_t *>(this->streambuf_.data()), buffer_size,
+ response_lifetime_, this->is_last_);
+
+ this->streambuf_.consume(buffer_size);
+
+ if (callback) {
+ callback(std::error_code());
+ }
+}
+
+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/apps/src/http-server/http-server/icn_response.h b/apps/src/http-server/http-server/icn_response.h
new file mode 100644
index 000000000..2194a5a7f
--- /dev/null
+++ b/apps/src/http-server/http-server/icn_response.h
@@ -0,0 +1,39 @@
+/*
+ * 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 "response.h"
+
+namespace icn_httpserver {
+
+class IcnResponse : public Response {
+
+public:
+ IcnResponse(std::shared_ptr<libl4::http::HTTPServerPublisher> producer,
+ std::string ndn_name, std::string ndn_path);
+
+ void send(const SendCallback &callback = nullptr) override;
+
+ void setResponseLifetime(
+ const std::chrono::milliseconds &response_lifetime) override;
+
+private:
+ std::string ndn_name_;
+ std::string ndn_path_;
+ std::shared_ptr<libl4::http::HTTPServerPublisher> publisher_;
+};
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/request.cc b/apps/src/http-server/http-server/request.cc
new file mode 100644
index 000000000..e754d645b
--- /dev/null
+++ b/apps/src/http-server/http-server/request.cc
@@ -0,0 +1,71 @@
+/*
+ * 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"
+
+using namespace std;
+
+inline bool caseInsCharCompareN(char a, char b) {
+ return (toupper(a) == toupper(b));
+}
+
+inline bool caseInsCharCompareW(wchar_t a, wchar_t b) {
+ return (towupper(a) == towupper(b));
+}
+
+bool caseInsCompare(const string &s1, const string &s2) {
+ return ((s1.size() == s2.size()) &&
+ equal(s1.begin(), s1.end(), s2.begin(), caseInsCharCompareN));
+}
+
+bool caseInsCompare(const wstring &s1, const wstring &s2) {
+ return ((s1.size() == s2.size()) &&
+ equal(s1.begin(), s1.end(), s2.begin(), caseInsCharCompareW));
+}
+
+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 std::smatch &Request::getPath_match() const { return path_match_; }
+
+void Request::setPath_match(const std::smatch &path_match) {
+ Request::path_match_ = path_match;
+}
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/request.h b/apps/src/http-server/http-server/request.h
new file mode 100644
index 000000000..f9b2a73df
--- /dev/null
+++ b/apps/src/http-server/http-server/request.h
@@ -0,0 +1,91 @@
+/*
+ * 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 "common.h"
+#include "content.h"
+
+using namespace std;
+
+inline bool caseInsCharCompareN(char a, char b);
+
+inline bool caseInsCharCompareW(wchar_t a, wchar_t b);
+
+bool caseInsCompare(const string &s1, const string &s2);
+
+bool caseInsCompare(const wstring &s1, const wstring &s2);
+
+namespace icn_httpserver {
+
+class iequal_to {
+public:
+ bool operator()(const std::string &key1, const std::string &key2) const {
+ return caseInsCompare(key1, key2);
+ }
+};
+
+class ihash {
+public:
+ size_t operator()(const std::string &key) const {
+ std::size_t seed = 0;
+ for (auto &c : key) {
+ std::hash<char> hasher;
+ seed ^= hasher(c) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ }
+ return seed;
+ }
+};
+
+class Request {
+public:
+ Request();
+
+ virtual void read_remote_endpoint_data(socket_type &socket){};
+
+ virtual ~Request() = default;
+
+ 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();
+
+ asio::streambuf &getStreambuf() { return streambuf_; }
+
+ Content &getContent();
+
+ const std::smatch &getPath_match() const;
+
+ void setPath_match(const std::smatch &path_match);
+
+protected:
+ std::string method_, path_, http_version_;
+ Content content_;
+ std::unordered_multimap<std::string, std::string, ihash, iequal_to> header_;
+ std::smatch path_match_;
+ asio::streambuf streambuf_;
+};
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/response.cc b/apps/src/http-server/http-server/response.cc
new file mode 100644
index 000000000..ccb249e4a
--- /dev/null
+++ b/apps/src/http-server/http-server/response.cc
@@ -0,0 +1,48 @@
+/*
+ * 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"
+#include "common.h"
+
+#define DEFAULT_LIFETIME 1000 * 1000
+
+namespace icn_httpserver {
+
+Response::Response()
+ : std::ostream(&streambuf_), is_last_(false), response_length_(0),
+ response_lifetime_(DEFAULT_LIFETIME) {}
+
+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; }
+
+const std::chrono::milliseconds &Response::getResponseLifetime() const {
+ return response_lifetime_;
+}
+
+void Response::setResponseLifetime(
+ const std::chrono::milliseconds &response_lifetime) {
+ Response::response_lifetime_ = response_lifetime;
+}
+
+void Response::setResponseLength(std::size_t length) {
+ response_length_ = length;
+}
+
+} // end namespace icn_httpserver
diff --git a/apps/src/http-server/http-server/response.h b/apps/src/http-server/http-server/response.h
new file mode 100644
index 000000000..9cc2e61ab
--- /dev/null
+++ b/apps/src/http-server/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.
+ */
+
+#pragma once
+
+#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);
+
+ const std::chrono::milliseconds &getResponseLifetime() const;
+
+ virtual void
+ setResponseLifetime(const std::chrono::milliseconds &response_lifetime);
+
+protected:
+ asio::streambuf streambuf_;
+ bool is_last_;
+ std::size_t response_length_;
+ std::chrono::milliseconds response_lifetime_;
+};
+
+} // end namespace icn_httpserver \ No newline at end of file
diff --git a/apps/src/http-server/http-server/socket_request.cc b/apps/src/http-server/http-server/socket_request.cc
new file mode 100644
index 000000000..321d9c61a
--- /dev/null
+++ b/apps/src/http-server/http-server/socket_request.cc
@@ -0,0 +1,38 @@
+/*
+ * 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/apps/src/http-server/http-server/socket_request.h b/apps/src/http-server/http-server/socket_request.h
new file mode 100644
index 000000000..c6566a207
--- /dev/null
+++ b/apps/src/http-server/http-server/socket_request.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#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
diff --git a/apps/src/http-server/http-server/socket_response.cc b/apps/src/http-server/http-server/socket_response.cc
new file mode 100644
index 000000000..5095c614f
--- /dev/null
+++ b/apps/src/http-server/http-server/socket_response.cc
@@ -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.
+ */
+
+#include "socket_response.h"
+
+namespace icn_httpserver {
+
+SocketResponse::SocketResponse(std::shared_ptr<asio::ip::tcp::socket> socket)
+ : socket_(socket) {}
+
+SocketResponse::~SocketResponse(){};
+
+void SocketResponse::send(const SendCallback &callback) {
+ asio::async_write(
+ *this->socket_, this->streambuf_,
+ [callback](const std::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/apps/src/http-server/http-server/socket_response.h b/apps/src/http-server/http-server/socket_response.h
new file mode 100644
index 000000000..b582809dc
--- /dev/null
+++ b/apps/src/http-server/http-server/socket_response.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#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