diff options
author | Jordan Augé <jordan.auge+fdio@email.com> | 2017-02-24 14:58:01 +0100 |
---|---|---|
committer | Jordan Augé <jordan.auge+fdio@cisco.com> | 2017-02-24 18:36:29 +0000 |
commit | 85a341d645b57b7cd88a26ed2ea0a314704240ea (patch) | |
tree | bdda2b35003aae20103a796f86daced160b8a730 /emu-radio/common-library/tcp-server.cc | |
parent | 9b30fc10fb1cbebe651e5a107e8ca5b24de54675 (diff) |
Initial commit: vICN
Change-Id: I7ce66c4e84a6a1921c63442f858b49e083adc7a7
Signed-off-by: Jordan Augé <jordan.auge+fdio@cisco.com>
Diffstat (limited to 'emu-radio/common-library/tcp-server.cc')
-rw-r--r-- | emu-radio/common-library/tcp-server.cc | 146 |
1 files changed, 146 insertions, 0 deletions
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 <boost::asio::ip::tcp::socket> 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 <boost::asio::ip::tcp::socket> socket) +{ + // Set timeout on the following boost::asio::async-read or write function + std::shared_ptr <boost::asio::deadline_timer> timer; + if (read_timeout > 0) + timer = set_timeout_on_socket (socket, read_timeout); + + std::shared_ptr <boost::asio::streambuf> 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<const uint8_t *> (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 <boost::asio::deadline_timer> +TcpServer::set_timeout_on_socket (std::shared_ptr <boost::asio::ip::tcp::socket> socket, long seconds) +{ + std::shared_ptr <boost::asio::deadline_timer> 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 |