diff --git a/i2pcontrol/I2PControlServer.cpp b/i2pcontrol/I2PControlServer.cpp index 5c956112..0a945c91 100644 --- a/i2pcontrol/I2PControlServer.cpp +++ b/i2pcontrol/I2PControlServer.cpp @@ -8,175 +8,163 @@ namespace i2p { namespace client { - I2PControlService::I2PControlService(const std::string& address, int port, const std::string& pass) - : m_Session(std::make_shared(m_Service, pass)), - m_IsRunning(false), m_Thread(nullptr), - m_Acceptor(m_Service, boost::asio::ip::tcp::endpoint( - boost::asio::ip::address::from_string(address), port) - ) - { +I2PControlService::I2PControlService(const std::string& address, int port, const std::string& pass) + : m_Session(std::make_shared(m_Service, pass)), + m_IsRunning(false), m_Thread(nullptr), + m_Acceptor(m_Service, boost::asio::ip::tcp::endpoint( + boost::asio::ip::address::from_string(address), port) + ) +{ + +} + +I2PControlService::~I2PControlService() +{ + Stop(); +} + +void I2PControlService::Start() +{ + if(!m_IsRunning) { + Accept(); + m_Session->start(); + m_IsRunning = true; + m_Thread = new std::thread(std::bind(&I2PControlService::Run, this)); } +} - I2PControlService::~I2PControlService () - { - Stop (); - } - - void I2PControlService::Start () - { - if (!m_IsRunning) - { - Accept (); - m_Session->start(); - m_IsRunning = true; - m_Thread = new std::thread (std::bind (&I2PControlService::Run, this)); - } - } - - void I2PControlService::Stop () - { - if (m_IsRunning) - { - m_IsRunning = false; - m_Acceptor.cancel (); - m_Session->stop(); - // Release ownership before the io_service is stopped and destroyed - m_Session.reset(); - m_Service.stop (); - if (m_Thread) - { - m_Thread->join (); - delete m_Thread; - m_Thread = nullptr; - } - } - } - - void I2PControlService::Run () - { - while (m_IsRunning) - { - try - { - m_Service.run (); - } - catch (std::exception& ex) - { - LogPrint (eLogError, "I2PControl: ", ex.what ()); - } +void I2PControlService::Stop() +{ + if(m_IsRunning) { + m_IsRunning = false; + m_Acceptor.cancel(); + m_Session->stop(); + // Release ownership before the io_service is stopped and destroyed + m_Session.reset(); + m_Service.stop(); + if(m_Thread) + { + m_Thread->join(); + delete m_Thread; + m_Thread = nullptr; } } +} - void I2PControlService::Accept () +void I2PControlService::Run() +{ + while(m_IsRunning) { + try { + m_Service.run(); + } catch(const std::exception& ex) { + LogPrint(eLogError, "I2PControl: ", ex.what()); + } + } +} + +void I2PControlService::Accept() +{ + auto newSocket = std::make_shared(m_Service); + m_Acceptor.async_accept(*newSocket, std::bind(&I2PControlService::HandleAccept, this, + std::placeholders::_1, newSocket)); +} + +void I2PControlService::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket) +{ + if(ecode != boost::asio::error::operation_aborted) + Accept(); + + if(!ecode) { - auto newSocket = std::make_shared (m_Service); - m_Acceptor.async_accept (*newSocket, std::bind (&I2PControlService::HandleAccept, this, - std::placeholders::_1, newSocket)); + LogPrint(eLogInfo, "New I2PControl request from ", socket->remote_endpoint()); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + ReadRequest(socket); } + else + LogPrint(eLogError, "I2PControl accept error: ", ecode.message()); +} - void I2PControlService::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket) - { - if (ecode != boost::asio::error::operation_aborted) - Accept (); - - if (!ecode) - { - LogPrint (eLogInfo, "New I2PControl request from ", socket->remote_endpoint ()); - std::this_thread::sleep_for (std::chrono::milliseconds(5)); - ReadRequest (socket); - } - else - LogPrint (eLogError, "I2PControl accept error: ", ecode.message ()); - } - - void I2PControlService::ReadRequest (std::shared_ptr socket) - { - auto request = std::make_shared(); - socket->async_read_some ( +void I2PControlService::ReadRequest(std::shared_ptr socket) +{ + auto request = std::make_shared(); + socket->async_read_some( #if BOOST_VERSION >= 104900 - boost::asio::buffer (*request), + boost::asio::buffer(*request), #else - boost::asio::buffer (request->data (), request->size ()), + boost::asio::buffer(request->data(), request->size()), #endif - std::bind(&I2PControlService::HandleRequestReceived, this, - std::placeholders::_1, std::placeholders::_2, socket, request)); + std::bind(&I2PControlService::HandleRequestReceived, this, + std::placeholders::_1, std::placeholders::_2, socket, request)); +} + +void I2PControlService::HandleRequestReceived(const boost::system::error_code& ecode, + size_t bytes_transferred, std::shared_ptr socket, + std::shared_ptr buf) +{ + if(ecode) { + LogPrint(eLogError, "I2PControl read error: ", ecode.message()); + return; } - void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode, - size_t bytes_transferred, std::shared_ptr socket, - std::shared_ptr buf) - { - if (ecode) - { - LogPrint (eLogError, "I2PControl read error: ", ecode.message ()); - } - else - { - try - { - bool isHtml = !memcmp (buf->data (), "POST", 4); - std::stringstream ss; - ss.write (buf->data (), bytes_transferred); - if (isHtml) - { - std::string header; - while (!ss.eof () && header != "\r") - std::getline(ss, header); - if (ss.eof ()) - { - LogPrint (eLogError, "Malformed I2PControl request. HTTP header expected"); - return; // TODO: - } - } - - I2PControlSession::Response response = m_Session->handleRequest(ss); - SendResponse(socket, buf, response.toJsonString(), isHtml); - } - catch (const std::exception& ex) - { - LogPrint (eLogError, "I2PControl handle request: ", ex.what ()); - } - catch (...) - { - LogPrint (eLogError, "I2PControl handle request unknown exception"); + try { + bool isHtml = !memcmp(buf->data(), "POST", 4); + std::stringstream ss; + ss.write(buf->data(), bytes_transferred); + if(isHtml) { + std::string header; + while(!ss.eof() && header != "\r") + std::getline(ss, header); + if(ss.eof()) { + LogPrint(eLogError, "Malformed I2PControl request. HTTP header expected"); + return; // TODO: } } - } - void I2PControlService::SendResponse (std::shared_ptr socket, - std::shared_ptr buf, const std::string& response, bool isHtml) - { - size_t len = response.length (), offset = 0; - if (isHtml) - { - std::ostringstream header; - header << "HTTP/1.1 200 OK\r\n"; - header << "Connection: close\r\n"; - header << "Content-Length: " << boost::lexical_cast(len) << "\r\n"; - header << "Content-Type: application/json\r\n"; - header << "Date: "; - auto facet = new boost::local_time::local_time_facet ("%a, %d %b %Y %H:%M:%S GMT"); - header.imbue(std::locale (header.getloc(), facet)); - header << boost::posix_time::second_clock::local_time() << "\r\n"; - header << "\r\n"; - offset = header.str ().size (); - memcpy (buf->data (), header.str ().c_str (), offset); - } - memcpy (buf->data () + offset, response.c_str (), len); - boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), offset + len), - boost::asio::transfer_all (), - std::bind(&I2PControlService::HandleResponseSent, this, - std::placeholders::_1, std::placeholders::_2, socket, buf)); + I2PControlSession::Response response = m_Session->handleRequest(ss); + SendResponse(socket, buf, response.toJsonString(), isHtml); + } catch(const std::exception& ex) { + LogPrint(eLogError, "I2PControl handle request: ", ex.what()); + } catch(...) { + LogPrint(eLogError, "I2PControl handle request unknown exception"); } +} - void I2PControlService::HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, - std::shared_ptr socket, std::shared_ptr buf) - { - if (ecode) - LogPrint (eLogError, "I2PControl write error: ", ecode.message ()); - socket->close (); - } +void I2PControlService::SendResponse(std::shared_ptr socket, + std::shared_ptr buf, const std::string& response, bool isHtml) +{ + size_t len = response.length(), offset = 0; + if(isHtml) { + std::ostringstream header; + header << "HTTP/1.1 200 OK\r\n"; + header << "Connection: close\r\n"; + header << "Content-Length: " << boost::lexical_cast(len) << "\r\n"; + header << "Content-Type: application/json\r\n"; + header << "Date: "; + auto facet = new boost::local_time::local_time_facet("%a, %d %b %Y %H:%M:%S GMT"); + header.imbue(std::locale(header.getloc(), facet)); + header << boost::posix_time::second_clock::local_time() << "\r\n"; + header << "\r\n"; + offset = header.str().size(); + memcpy(buf->data(), header.str().c_str(), offset); + } + memcpy(buf->data() + offset, response.c_str(), len); + boost::asio::async_write( + *socket, boost::asio::buffer(buf->data(), offset + len), + boost::asio::transfer_all(), std::bind( + &I2PControlService::HandleResponseSent, this, + std::placeholders::_1, std::placeholders::_2, socket, buf + ) + ); +} + +void I2PControlService::HandleResponseSent(const boost::system::error_code& ecode, std::size_t bytes_transferred, + std::shared_ptr socket, std::shared_ptr buf) +{ + if(ecode) + LogPrint(eLogError, "I2PControl write error: ", ecode.message()); + socket->close(); +} } } diff --git a/i2pcontrol/I2PControlServer.h b/i2pcontrol/I2PControlServer.h index 2eb13654..48b84101 100644 --- a/i2pcontrol/I2PControlServer.h +++ b/i2pcontrol/I2PControlServer.h @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include namespace i2p { @@ -22,22 +20,22 @@ class I2PControlService { public: I2PControlService(const std::string& address, int port, const std::string& pass); - ~I2PControlService (); + ~I2PControlService(); - void Start (); - void Stop (); + void Start(); + void Stop(); private: - void Run (); - void Accept (); + void Run(); + void Accept(); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); - void ReadRequest (std::shared_ptr socket); - void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred, + void ReadRequest(std::shared_ptr socket); + void HandleRequestReceived(const boost::system::error_code& ecode, size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf); - void SendResponse (std::shared_ptr socket, + void SendResponse(std::shared_ptr socket, std::shared_ptr buf, const std::string& response, bool isHtml); - void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, + void HandleResponseSent(const boost::system::error_code& ecode, std::size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf); private: