diff --git a/BOB.cpp b/BOB.cpp index 0a908ad2..55d14293 100644 --- a/BOB.cpp +++ b/BOB.cpp @@ -16,6 +16,12 @@ namespace client { } + void BOBCommandSession::Terminate () + { + m_Socket.close (); + m_IsOpen = false; + } + void BOBCommandSession::Receive () { m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, BOB_COMMAND_BUFFER_SIZE - m_ReceiveBufferOffset), @@ -26,7 +32,10 @@ namespace client void BOBCommandSession::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) + { LogPrint ("BOB command channel read error: ", ecode.message ()); + Terminate (); + } else { size_t size = m_ReceiveBufferOffset + bytes_transferred; @@ -55,18 +64,67 @@ namespace client else { LogPrint (eLogError, "Malformed input of the BOB command channel"); - return; + Terminate (); } } + } + } + + void BOBCommandSession::Send (size_t len) + { + boost::asio::async_write (m_Socket, boost::asio::buffer (m_SendBuffer, len), + boost::asio::transfer_all (), + std::bind(&BOBCommandSession::HandleSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2)); + } + + void BOBCommandSession::HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) + { + if (ecode) + { + LogPrint ("BOB command channel send error: ", ecode.message ()); + Terminate (); + } + else + { if (m_IsOpen) Receive (); + else + Terminate (); } } + void BOBCommandSession::SendReplyOK (const char * msg) + { +#ifdef _MSC_VER + size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg); +#else + size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg); +#endif + Send (len); + } + + void BOBCommandSession::SendReplyError (const char * msg) + { +#ifdef _MSC_VER + size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg); +#else + size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg); +#endif + Send (len); + } + void BOBCommandSession::ZapCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: zap"); + Terminate (); + } + + void BOBCommandSession::QuitCommandHandler (const char * operand, size_t len) + { + LogPrint (eLogDebug, "BOB: quit"); m_IsOpen = false; + SendReplyOK ("Bye!"); } BOBCommandChannel::BOBCommandChannel (int port): @@ -74,6 +132,7 @@ namespace client m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)) { m_CommandHandlers[BOB_COMMAND_ZAP] = &BOBCommandSession::ZapCommandHandler; + m_CommandHandlers[BOB_COMMAND_QUIT] = &BOBCommandSession::QuitCommandHandler; } BOBCommandChannel::~BOBCommandChannel () diff --git a/BOB.h b/BOB.h index 25407058..d653a997 100644 --- a/BOB.h +++ b/BOB.h @@ -15,6 +15,10 @@ namespace client { const size_t BOB_COMMAND_BUFFER_SIZE = 1024; const char BOB_COMMAND_ZAP[] = "zap"; + const char BOB_COMMAND_QUIT[] = "quit"; + + const char BOB_REPLY_OK[] = "OK %s\n"; + const char BOB_REPLY_ERROR[] = "ERROR %s\n"; class BOBCommandChannel; class BOBCommandSession: public std::enable_shared_from_this @@ -23,19 +27,29 @@ namespace client BOBCommandSession (BOBCommandChannel& owner); ~BOBCommandSession (); + void Terminate (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; void Receive (); - void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); // command handlers void ZapCommandHandler (const char * operand, size_t len); + void QuitCommandHandler (const char * operand, size_t len); + + private: + + void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred); + + void Send (size_t len); + void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); + void SendReplyOK (const char * msg); + void SendReplyError (const char * msg); private: BOBCommandChannel& m_Owner; boost::asio::ip::tcp::socket m_Socket; - char m_ReceiveBuffer[BOB_COMMAND_BUFFER_SIZE + 1]; + char m_ReceiveBuffer[BOB_COMMAND_BUFFER_SIZE + 1], m_SendBuffer[BOB_COMMAND_BUFFER_SIZE + 1]; size_t m_ReceiveBufferOffset; bool m_IsOpen; };