aboutsummaryrefslogtreecommitdiffstats
path: root/icnet/http/icnet_http_server_acceptor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'icnet/http/icnet_http_server_acceptor.cc')
-rw-r--r--icnet/http/icnet_http_server_acceptor.cc171
1 files changed, 171 insertions, 0 deletions
diff --git a/icnet/http/icnet_http_server_acceptor.cc b/icnet/http/icnet_http_server_acceptor.cc
new file mode 100644
index 00000000..9406955d
--- /dev/null
+++ b/icnet/http/icnet_http_server_acceptor.cc
@@ -0,0 +1,171 @@
+/*
+ * 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 "icnet_http_server_acceptor.h"
+#include "icnet_http_request.h"
+#include "icnet_errors.h"
+#include "icnet_utils_uri.h"
+#include "icnet_utils_hash.h"
+
+namespace icnet {
+
+namespace http {
+
+HTTPServerAcceptor::HTTPServerAcceptor(std::string &&server_locator, OnHttpRequest callback)
+ : HTTPServerAcceptor(server_locator, callback) {
+}
+
+HTTPServerAcceptor::HTTPServerAcceptor(std::string &server_locator, OnHttpRequest callback)
+ : callback_(callback) {
+ utils::Uri uri;
+
+ uri.parseProtocolAndLocator(server_locator);
+ std::string protocol = uri.getProtocol();
+ std::string locator = uri.getLocator();
+
+ std::transform(locator.begin(),
+ locator.end(),
+ locator.begin(),
+ ::tolower);
+
+ std::transform(protocol.begin(),
+ protocol.end(),
+ protocol.begin(),
+ ::tolower);
+
+ if (protocol != "http") {
+ throw errors::RuntimeException("Malformed server_locator. The locator format should be in the form http://locator");
+ }
+
+ std::stringstream ss;
+
+ ss << "ccnx:/";
+ ss << locator;
+
+ acceptor_producer_ = std::make_shared<transport::ProducerSocket>(ss.str());
+}
+
+void HTTPServerAcceptor::listen(bool async) {
+ acceptor_producer_->setSocketOption(icnet::transport::ProducerCallbacksOptions::INTEREST_INPUT,
+ (icnet::transport::ProducerInterestCallback) bind(&HTTPServerAcceptor::processIncomingInterest,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+ acceptor_producer_->dispatch();
+
+ if (!async) {
+ acceptor_producer_->serveForever();
+ }
+}
+
+HttpRequest &&HTTPServerAcceptor::request() {
+ return std::move(request_);
+}
+
+void HTTPServerAcceptor::processIncomingInterest(transport::ProducerSocket &p, const transport::Interest &interest) {
+ // Temporary solution
+
+ transport::Name complete_name = interest.getName();
+
+ transport::Name request_name = complete_name.get(-1).isSegment() ? complete_name.getPrefix(-1) : complete_name;
+ transport::Name prefix;
+ acceptor_producer_->getSocketOption(transport::GeneralTransportOptions::NAME_PREFIX, prefix);
+
+ // Get the name of the HTTP method to compute
+ std::string method = request_name.get(prefix.getSegmentCount()).toString();
+ std::transform(method.begin(), method.end(), method.begin(), ::toupper);
+ std::string path;
+ std::string url_begin;
+
+ // This is done for getting rid of useless name components such as ccnx: or ndn:
+ if (request_name.getSegmentCount() > 2) {
+ std::string raw_path = request_name.getSubName(prefix.getSegmentCount() + 1).toString();
+ std::size_t pos = raw_path.find("/");
+ path = raw_path.substr(pos);
+ url_begin = prefix.getSubName(0).toString().substr(pos);
+ }
+
+ std::stringstream ss;
+ ss << "http:/" << url_begin << path;
+
+ std::string url = ss.str();
+ HTTPHeaders headers = {};
+ HTTPPayload payload = {};
+
+ if (method == "GET") {
+ HTTPRequest request(GET, url, headers, payload);
+ auto publisher = std::make_shared<HTTPServerPublisher>(request_name);
+ callback_(publisher, (uint8_t *) request.getRequestString().data(), request.getRequestString().size());
+ }
+}
+
+//void HTTPServerConnection::sendResponse() {
+//
+// std::thread t([]() {
+//
+// // 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);
+// }
+//
+// // Create new producer
+//
+// // Create timer for response availability
+// std::shared_ptr<core::Portal> portal;
+// po->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();
+// }
+// };
+//
+// std::function<void(transport::ProducerSocket, const core::Interest &interest)>
+// interest_enter_callback = [this, &wait_callback, &t]
+// (transport::ProducerSocket &p, const core::Interest &interest) {
+// t.cancel();
+// t.expires_from_now(boost::posix_time::seconds(5));
+// t.async_wait(wait_callback);
+// };
+//
+// p->setSocketOption(transport::ProducerCallbacksOptions::INTEREST_INPUT,
+// (transport::ProducerInterestCallback) interest_enter_callback);
+//
+// t.async_wait(wait_callback);
+//
+// p->serveForever();
+//
+// std::unique_lock<std::mutex> lock(thread_list_mtx_);
+// icn_producers_.erase(request_name);
+// });
+//
+// t.detach();
+//}
+
+}
+
+} \ No newline at end of file