summaryrefslogtreecommitdiffstatshomepage
path: root/server/session.cpp
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2019-12-07 03:36:21 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2019-12-07 03:36:21 +0300
commit00863566ec4601c65c435b74e575d49546a1c707 (patch)
tree479a0a6e96aba8191c7a65ea9bee2f4d5e3a4aba /server/session.cpp
parentadd stress_test.py (diff)
downloadmath-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.cpp113
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();
-}
-
-}