diff options
| author | Egor Tensin <Egor.Tensin@gmail.com> | 2019-12-07 03:36:21 +0300 |
|---|---|---|
| committer | Egor Tensin <Egor.Tensin@gmail.com> | 2019-12-07 03:36:21 +0300 |
| commit | 00863566ec4601c65c435b74e575d49546a1c707 (patch) | |
| tree | 479a0a6e96aba8191c7a65ea9bee2f4d5e3a4aba /server/session.cpp | |
| parent | add stress_test.py (diff) | |
| download | math-server-00863566ec4601c65c435b74e575d49546a1c707.tar.gz math-server-00863566ec4601c65c435b74e575d49546a1c707.zip | |
split server into multiple components
In a vague attempt to make header files more readable, split server/
into a number of components.
Also, refactor the unit tests to use the "Data-driven test cases" of
Boost.Test.
Diffstat (limited to 'server/session.cpp')
| -rw-r--r-- | server/session.cpp | 113 |
1 files changed, 0 insertions, 113 deletions
diff --git a/server/session.cpp b/server/session.cpp deleted file mode 100644 index 409ca5a..0000000 --- a/server/session.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "error.hpp" -#include "log.hpp" -#include "parser.hpp" -#include "session.hpp" -#include "session_manager.hpp" - -#include <boost/asio.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/system/error_code.hpp> -#include <boost/system/system_error.hpp> - -#include <cstddef> - -#include <exception> -#include <string> -#include <utility> - -namespace math::server { -namespace { - -std::string reply_to_string(double result) { - return boost::lexical_cast<std::string>(result); -} - -std::string calc_reply(const std::string& input) { - std::string reply; - try { - reply = reply_to_string(Parser{input}.exec()); - } catch (const std::exception& e) { - reply = e.what(); - } - return reply; -} - -} - -Session::Session(SessionManager& mgr, boost::asio::io_context& io_context) - : m_session_mgr{mgr}, m_strand{io_context}, m_socket{io_context} -{ } - -boost::asio::ip::tcp::socket& Session::socket() { - return m_socket; -} - -void Session::start() { - read(); -} - -void Session::stop() { - close(); -} - -void Session::close() { - try { - m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); - m_socket.close(); - } catch (const boost::system::system_error& e) { - throw Error{e.what()}; - } -} - -void Session::read() { - const auto self = shared_from_this(); - - // Stop at LF - boost::asio::async_read_until(m_socket, m_buffer, '\n', boost::asio::bind_executor(m_strand, - [this, self] (const boost::system::error_code& ec, std::size_t bytes) { - handle_read(ec, bytes); - })); -} - -void Session::handle_read(const boost::system::error_code& ec, std::size_t bytes) { - if (ec) { - log::error("%1%: %2%", __func__, ec.message()); - m_session_mgr.stop(shared_from_this()); - return; - } - - write(calc_reply(consume_input(bytes))); -} - -std::string Session::consume_input(std::size_t bytes) { - const auto data = boost::asio::buffer_cast<const char*>(m_buffer.data()); - const std::string input{data, bytes - 1}; - m_buffer.consume(bytes); - return input; -} - -void Session::write(std::string output) { - const auto self = shared_from_this(); - - // Include CR (so that Windows' telnet client works) - output += "\r\n"; - - boost::asio::const_buffer buffer{output.c_str(), output.length()}; - - boost::asio::async_write(m_socket, std::move(buffer), boost::asio::bind_executor(m_strand, - [this, self] (const boost::system::error_code& ec, std::size_t bytes) { - handle_write(ec, bytes); - })); -} - -void Session::handle_write(const boost::system::error_code& ec, std::size_t bytes) { - if (ec) { - log::error("%1%: %2%", __func__, ec.message()); - m_session_mgr.stop(shared_from_this()); - return; - } - - read(); -} - -} |
