From 85a341d645b57b7cd88a26ed2ea0a314704240ea Mon Sep 17 00:00:00 2001 From: Jordan Augé Date: Fri, 24 Feb 2017 14:58:01 +0100 Subject: Initial commit: vICN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7ce66c4e84a6a1921c63442f858b49e083adc7a7 Signed-off-by: Jordan Augé --- emu-radio/common-library/tcp-server.cc | 146 +++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 emu-radio/common-library/tcp-server.cc (limited to 'emu-radio/common-library/tcp-server.cc') diff --git a/emu-radio/common-library/tcp-server.cc b/emu-radio/common-library/tcp-server.cc new file mode 100644 index 00000000..6b9129a1 --- /dev/null +++ b/emu-radio/common-library/tcp-server.cc @@ -0,0 +1,146 @@ +/* + * 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 "tcp-server.h" + +TcpServer::TcpServer (unsigned short port, long read_timeout) + : port (port), + acceptor (io_service), + read_timeout (read_timeout) +{ +} + +TcpServer::~TcpServer () +{ +} + +void TcpServer::setHandler (const HandlerFunction &handler) +{ + this->handler = handler; +} + +void TcpServer::start () +{ + if (io_service.stopped ()) + io_service.reset (); + + boost::asio::ip::tcp::endpoint endpoint; + endpoint = boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4 (), port); + + acceptor.open (endpoint.protocol ()); + acceptor.set_option (boost::asio::socket_base::reuse_address (true)); + acceptor.bind (endpoint); + acceptor.listen (); + + accept (); + + //Set interrupt callbacks + + boost::asio::io_service io_service; + boost::asio::signal_set signals (io_service, SIGINT, SIGQUIT); + + signals.async_wait ([this] (const boost::system::error_code &errorCode, int) + { + std::cout << "Gracefully terminating tcp server" << std::endl; + this->io_service.reset (); + this->acceptor.cancel (); + }); + + io_service.run (); +} + +void TcpServer::accept () +{ + //Create new socket for this connection + //Shared_ptr is used to pass temporary objects to the asynchronous functions + std::shared_ptr socket (new boost::asio::ip::tcp::socket (io_service)); + acceptor.async_accept (*socket, [this, socket] (const boost::system::error_code &ec) + { + accept (); + + if (ec) + { + if (ec == boost::asio::error::operation_aborted) // when the socket is closed by someone + return; + } + + processIncomingData (socket); + }); +} + +void TcpServer::processIncomingData (std::shared_ptr socket) +{ + // Set timeout on the following boost::asio::async-read or write function + std::shared_ptr timer; + if (read_timeout > 0) + timer = set_timeout_on_socket (socket, read_timeout); + + std::shared_ptr buffer (new boost::asio::streambuf ()); + + boost::asio::async_read_until (*socket, *buffer, "\r\n\r\n", [this, timer, buffer, socket] (const boost::system::error_code &error, std::size_t bytes_transferred) + { + if (read_timeout > 0) + timer->cancel (); + + if (error) + { + std::cerr << "Boost error code is not null! ERROR: " << error << std::endl; + return; + } + + std::size_t bufferSize = buffer->size (); + buffer->commit (buffer->size ()); + const uint8_t *data = boost::asio::buffer_cast (buffer->data ()); + + std::string reply = handler (data, bufferSize); + + if (reply != "") + { + + boost::asio::async_write (*socket, boost::asio::buffer (reply.c_str (), reply + .size ()), [this] (boost::system::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + std::cout << "Reply sent!" << std::endl; + } + else + { + std::cerr << "ERROR! Reply not sent." << std::endl; + } + }); + + } + }); + +} + +std::shared_ptr +TcpServer::set_timeout_on_socket (std::shared_ptr socket, long seconds) +{ + std::shared_ptr timer (new 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; + std::cout << "Connection timeout!" << std::endl; + socket->lowest_layer ().shutdown (boost::asio::ip::tcp::socket::shutdown_both, ec); + socket->lowest_layer ().close (); + } + }); + return timer; +} \ No newline at end of file -- cgit 1.2.3-korg