diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/worldserver/Master.cpp | 15 | ||||
-rw-r--r-- | src/server/worldserver/Master.h | 6 | ||||
-rw-r--r-- | src/server/worldserver/RemoteAccess/RASession.cpp | 204 | ||||
-rw-r--r-- | src/server/worldserver/RemoteAccess/RASession.h | 23 | ||||
-rw-r--r-- | src/server/worldserver/RemoteAccess/RASocket.cpp | 425 | ||||
-rw-r--r-- | src/server/worldserver/RemoteAccess/RASocket.h | 64 |
6 files changed, 214 insertions, 523 deletions
diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index 4669168042c..c529e6b6478 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -41,7 +41,6 @@ #include "BigNumber.h" #include "OpenSSLCrypto.h" #include "AsyncAcceptor.h" -#include "RASession.h" #ifdef _WIN32 #include "ServiceWin32.h" @@ -163,8 +162,10 @@ int Master::Run() cliThread = new std::thread(CliThread); } + AsyncAcceptor<RASession>* raAcceptor = nullptr; + if (sConfigMgr->GetBoolDefault("Ra.Enable", false)) - StartRaSocketAcceptor(_ioService); + raAcceptor = StartRaSocketAcceptor(_ioService); #if defined(_WIN32) || defined(__linux__) @@ -246,9 +247,7 @@ int Master::Run() ///- Start up freeze catcher thread if (uint32 freezeDelay = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0)) - { freezeDetectorThread = new std::thread(FreezeDetectorThread, freezeDelay); - } ///- Launch the world listener socket uint16 worldPort = uint16(sWorld->getIntConfig(CONFIG_PORT_WORLD)); @@ -271,7 +270,6 @@ int Master::Run() // when the main thread closes the singletons get unloaded // since worldrunnable uses them, it will crash if unloaded after master worldThread.join(); - //rarThread.join(); if (soapThread != nullptr) { @@ -279,6 +277,9 @@ int Master::Run() delete soapThread; } + if (raAcceptor != nullptr) + delete raAcceptor; + // set server offline LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realmID); @@ -469,10 +470,10 @@ void Master::ClearOnlineAccounts() CharacterDatabase.DirectExecute("UPDATE character_battleground_data SET instanceId = 0"); } -void Master::StartRaSocketAcceptor(boost::asio::io_service& ioService) +AsyncAcceptor<RASession>* Master::StartRaSocketAcceptor(boost::asio::io_service& ioService) { uint16 raPort = uint16(sConfigMgr->GetIntDefault("Ra.Port", 3443)); std::string raListener = sConfigMgr->GetStringDefault("Ra.IP", "0.0.0.0"); - AsyncAcceptor<RASession> raAcceptor(ioService, raListener, raPort); + return new AsyncAcceptor<RASession>(ioService, raListener, raPort); } diff --git a/src/server/worldserver/Master.h b/src/server/worldserver/Master.h index 0c6836f25b8..86059e6417a 100644 --- a/src/server/worldserver/Master.h +++ b/src/server/worldserver/Master.h @@ -25,6 +25,10 @@ #include <boost/asio/io_service.hpp> #include "Common.h" +#include "RASession.h" + +template<typename T> +class AsyncAcceptor; /// Start the server class Master @@ -43,7 +47,7 @@ class Master void _StopDB(); void ClearOnlineAccounts(); - void StartRaSocketAcceptor(boost::asio::io_service& ioService); + AsyncAcceptor<RASession>* StartRaSocketAcceptor(boost::asio::io_service& ioService); }; #define sMaster Master::instance() diff --git a/src/server/worldserver/RemoteAccess/RASession.cpp b/src/server/worldserver/RemoteAccess/RASession.cpp index 359b18f1039..536ce22839b 100644 --- a/src/server/worldserver/RemoteAccess/RASession.cpp +++ b/src/server/worldserver/RemoteAccess/RASession.cpp @@ -18,35 +18,201 @@ #include <memory> #include <boost/asio/write.hpp> +#include <boost/asio/read_until.hpp> +#include <boost/array.hpp> #include "RASession.h" +#include "AccountMgr.h" using boost::asio::ip::tcp; -void RASession::AsyncRead() +void RASession::Start() { - auto self(shared_from_this()); + boost::asio::socket_base::bytes_readable command(true); + _socket.io_control(command); + std::size_t bytes_readable = command.get(); - _socket.async_read_some(boost::asio::buffer(_readBuffer, 1), [this, self](boost::system::error_code error, size_t transferedBytes) + // Check if there are bytes available, if they are, then the client is requesting the negotiation + if (bytes_readable > 0) { - if (!error && transferedBytes == 1) - { - // let the magic happen - } - else - { - _socket.close(); - } - }); + // Handle subnegotiation + boost::array<char, 1024> buf; + std::size_t length = _socket.read_some(boost::asio::buffer(buf)); + + // Send the end-of-negotiation packet + uint8 const reply[2] = { 0xFF, 0xF0 }; + _socket.write_some(boost::asio::buffer(reply)); + } + + Send("Authentication Required\r\n"); + Send("Username: "); + + std::string username = ReadString(); + + if (username.empty()) + return; + + TC_LOG_INFO("commands.ra", "Accepting RA connection from user %s (IP: %s)", username.c_str(), GetRemoteIpAddress().c_str()); + + Send("Password: "); + + std::string password = ReadString(); + if (password.empty()) + return; + + if (!CheckAccessLevel(username) || !CheckPassword(username, password)) + { + Send("Authentication failed\r\n"); + _socket.close(); + return; + } + + TC_LOG_INFO("commands.ra", "User %s (IP: %s) authenticated correctly to RA", username.c_str(), GetRemoteIpAddress().c_str()); + + // Authentication successful, send the motd + Send(std::string(std::string(sWorld->GetMotd()) + "\r\n").c_str()); + + // Read commands + while (true) + { + Send("TC>"); + std::string command = ReadString(); + + if (ProcessCommand(command)) + break; + } + + _socket.close(); +} + +int RASession::Send(const char* data) +{ + std::ostream os(&_writeBuffer); + os << data; + size_t written = _socket.send(_writeBuffer.data()); + _writeBuffer.consume(written); + return written; +} + +std::string RASession::ReadString() +{ + boost::system::error_code error; + size_t read = boost::asio::read_until(_socket, _readBuffer, "\r\n", error); + if (!read) + { + _socket.close(); + return ""; + } + + std::string line; + std::istream is(&_readBuffer); + std::getline(is, line); + + if (*line.rbegin() == '\r') + line.erase(line.length() - 1); + + return line; +} + +bool RASession::CheckAccessLevel(const std::string& user) +{ + std::string safeUser = user; + + AccountMgr::normalizeString(safeUser); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS); + stmt->setString(0, safeUser); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (!result) + { + TC_LOG_INFO("commands.ra", "User %s does not exist in database", user.c_str()); + return false; + } + + Field* fields = result->Fetch(); + + if (fields[1].GetUInt8() < sConfigMgr->GetIntDefault("RA.MinLevel", 3)) + { + TC_LOG_INFO("commands.ra", "User %s has no privilege to login", user.c_str()); + return false; + } + else if (fields[2].GetInt32() != -1) + { + TC_LOG_INFO("commands.ra", "User %s has to be assigned on all realms (with RealmID = '-1')", user.c_str()); + return false; + } + + return true; } -void RASession::AsyncWrite(std::size_t length) +bool RASession::CheckPassword(const std::string& user, const std::string& pass) { - boost::asio::async_write(_socket, boost::asio::buffer(_writeBuffer, length), [this](boost::system::error_code error, std::size_t /*length*/) + std::string safe_user = user; + std::transform(safe_user.begin(), safe_user.end(), safe_user.begin(), ::toupper); + AccountMgr::normalizeString(safe_user); + + std::string safe_pass = pass; + AccountMgr::normalizeString(safe_pass); + std::transform(safe_pass.begin(), safe_pass.end(), safe_pass.begin(), ::toupper); + + std::string hash = AccountMgr::CalculateShaPassHash(safe_user, safe_pass); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME); + + stmt->setString(0, safe_user); + stmt->setString(1, hash); + + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (!result) { - if (error) - { - _socket.close(); - } - }); + TC_LOG_INFO("commands.ra", "Wrong password for user: %s", user.c_str()); + return false; + } + + return true; } +bool RASession::ProcessCommand(std::string& command) +{ + if (command.length() == 0) + return true; + + TC_LOG_INFO("commands.ra", "Received command: %s", command.c_str()); + + // handle quit, exit and logout commands to terminate connection + if (command == "quit" || command == "exit" || command == "logout") + { + Send("Bye\r\n"); + return true; + } + + // Obtain a new promise per command + if (_commandExecuting != nullptr) + delete _commandExecuting; + + _commandExecuting = new std::promise<void>(); + + CliCommandHolder* cmd = new CliCommandHolder(this, command.c_str(), &RASession::CommandPrint, &RASession::CommandFinished); + sWorld->QueueCliCommand(cmd); + + // Wait for the command to finish + _commandExecuting->get_future().wait(); + + return false; +} + +void RASession::CommandPrint(void* callbackArg, const char* text) +{ + if (!text || !*text) + return; + + RASession* session = static_cast<RASession*>(callbackArg); + session->Send(text); +} + +void RASession::CommandFinished(void* callbackArg, bool success) +{ + RASession* session = static_cast<RASession*>(callbackArg); + session->_commandExecuting->set_value(); +} diff --git a/src/server/worldserver/RemoteAccess/RASession.h b/src/server/worldserver/RemoteAccess/RASession.h index a467c387858..f3ef2a6a86a 100644 --- a/src/server/worldserver/RemoteAccess/RASession.h +++ b/src/server/worldserver/RemoteAccess/RASession.h @@ -21,8 +21,11 @@ #include <memory> #include <boost/asio/ip/tcp.hpp> +#include <boost/asio/streambuf.hpp> #include "Common.h" +#include <future> + using boost::asio::ip::tcp; const size_t bufferSize = 4096; @@ -32,25 +35,31 @@ const size_t bufferSize = 4096; class RASession : public std::enable_shared_from_this <RASession> { public: - RASession(tcp::socket socket) : _socket(std::move(socket)) + RASession(tcp::socket socket) : _socket(std::move(socket)), _commandExecuting(nullptr) { } - void Start() - { - AsyncRead(); - } + void Start(); const std::string GetRemoteIpAddress() const { return _socket.remote_endpoint().address().to_string(); }; unsigned short GetRemotePort() const { return _socket.remote_endpoint().port(); } private: + int Send(const char* data); void AsyncRead(); void AsyncWrite(size_t length); + std::string ReadString(); + bool CheckAccessLevel(const std::string& user); + bool CheckPassword(const std::string& user, const std::string& pass); + bool ProcessCommand(std::string& command); + + static void CommandPrint(void* callbackArg, const char* text); + static void CommandFinished(void* callbackArg, bool success); tcp::socket _socket; - char _readBuffer[BUFFER_SIZE]; - char _writeBuffer[BUFFER_SIZE]; + boost::asio::streambuf _readBuffer; + boost::asio::streambuf _writeBuffer; + std::promise<void>* _commandExecuting; }; #endif diff --git a/src/server/worldserver/RemoteAccess/RASocket.cpp b/src/server/worldserver/RemoteAccess/RASocket.cpp deleted file mode 100644 index 698d3c949cd..00000000000 --- a/src/server/worldserver/RemoteAccess/RASocket.cpp +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/** \file - \ingroup Trinityd -*/ - -#include "Common.h" -#include "Configuration/Config.h" -#include "Database/DatabaseEnv.h" -#include "AccountMgr.h" -#include "Log.h" -#include "RASocket.h" -#include "Util.h" -#include "World.h" -#include "SHA1.h" -#include "ace/OS_NS_unistd.h" - -RASocket::RASocket() -{ - _minLevel = uint8(sConfigMgr->GetIntDefault("RA.MinLevel", 3)); - _commandExecuting = false; -} - -int RASocket::open(void *) -{ - ACE_INET_Addr remoteAddress; - - if (peer().get_remote_addr(remoteAddress) == -1) - { - TC_LOG_ERROR("server.worldserver", "RASocket::open: peer().get_remote_addr error is %s", ACE_OS::strerror(errno)); - return -1; - } - - TC_LOG_INFO("commands.ra", "Incoming connection from %s", remoteAddress.get_host_addr()); - - return activate(); -} - -int RASocket::handle_close(ACE_HANDLE /*handle*/, ACE_Reactor_Mask /*mask*/) -{ - TC_LOG_INFO("commands.ra", "Closing connection"); - peer().close_reader(); - wait(); - // While the above wait() will wait for the ::svc() to finish, it will not wait for the async event - // RASocket::commandfinished to be completed. Calling destroy() before the latter function ends - // will lead to using a freed pointer -> crash. - while (_commandExecuting.value()) - ACE_OS::sleep(1); - - destroy(); - return 0; -} - -int RASocket::send(const std::string& line) -{ -#ifdef MSG_NOSIGNAL - ssize_t n = peer().send(line.c_str(), line.length(), MSG_NOSIGNAL); -#else - ssize_t n = peer().send(line.c_str(), line.length()); -#endif // MSG_NOSIGNAL - - return n == ssize_t(line.length()) ? 0 : -1; -} - -int RASocket::recv_line(ACE_Message_Block& buffer) -{ - char byte; - for (;;) - { - ssize_t n = peer().recv(&byte, sizeof(byte)); - - if (n < 0) - return -1; - - if (n == 0) - { - // EOF, connection was closed - errno = ECONNRESET; - return -1; - } - - ACE_ASSERT(n == sizeof(byte)); - - if (byte == '\n') - break; - else if (byte == '\r') /* Ignore CR */ - continue; - else if (buffer.copy(&byte, sizeof(byte)) == -1) - return -1; - } - - const char nullTerm = '\0'; - if (buffer.copy(&nullTerm, sizeof(nullTerm)) == -1) - return -1; - - return 0; -} - -int RASocket::recv_line(std::string& out_line) -{ - char buf[4096]; - - ACE_Data_Block db(sizeof (buf), - ACE_Message_Block::MB_DATA, - buf, - 0, - 0, - ACE_Message_Block::DONT_DELETE, - 0); - - ACE_Message_Block message_block(&db, - ACE_Message_Block::DONT_DELETE, - 0); - - if (recv_line(message_block) == -1) - { - TC_LOG_DEBUG("commands.ra", "Recv error %s", ACE_OS::strerror(errno)); - return -1; - } - - out_line = message_block.rd_ptr(); - - return 0; -} - -int RASocket::process_command(const std::string& command) -{ - if (command.length() == 0) - return 0; - - TC_LOG_INFO("commands.ra", "Received command: %s", command.c_str()); - - // handle quit, exit and logout commands to terminate connection - if (command == "quit" || command == "exit" || command == "logout") { - (void) send("Bye\r\n"); - return -1; - } - - _commandExecuting = true; - CliCommandHolder* cmd = new CliCommandHolder(this, command.c_str(), &RASocket::zprint, &RASocket::commandFinished); - sWorld->QueueCliCommand(cmd); - - // wait for result - ACE_Message_Block* mb; - for (;;) - { - if (getq(mb) == -1) - return -1; - - if (mb->msg_type() == ACE_Message_Block::MB_BREAK) - { - mb->release(); - break; - } - - if (send(std::string(mb->rd_ptr(), mb->length())) == -1) - { - mb->release(); - return -1; - } - - mb->release(); - } - - return 0; -} - -int RASocket::check_access_level(const std::string& user) -{ - std::string safeUser = user; - - AccountMgr::normalizeString(safeUser); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS); - stmt->setString(0, safeUser); - PreparedQueryResult result = LoginDatabase.Query(stmt); - - if (!result) - { - TC_LOG_INFO("commands.ra", "User %s does not exist in database", user.c_str()); - return -1; - } - - Field* fields = result->Fetch(); - - if (fields[1].GetUInt8() < _minLevel) - { - TC_LOG_INFO("commands.ra", "User %s has no privilege to login", user.c_str()); - return -1; - } - else if (fields[2].GetInt32() != -1) - { - TC_LOG_INFO("commands.ra", "User %s has to be assigned on all realms (with RealmID = '-1')", user.c_str()); - return -1; - } - - return 0; -} - -int RASocket::check_password(const std::string& user, const std::string& pass) -{ - std::string safe_user = user; - AccountMgr::normalizeString(safe_user); - - std::string safe_pass = pass; - AccountMgr::normalizeString(safe_pass); - - std::string hash = AccountMgr::CalculateShaPassHash(safe_user, safe_pass); - - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME); - - stmt->setString(0, safe_user); - stmt->setString(1, hash); - - PreparedQueryResult result = LoginDatabase.Query(stmt); - - if (!result) - { - TC_LOG_INFO("commands.ra", "Wrong password for user: %s", user.c_str()); - return -1; - } - - return 0; -} - -int RASocket::authenticate() -{ - if (send(std::string("Username: ")) == -1) - return -1; - - std::string user; - if (recv_line(user) == -1) - return -1; - - if (send(std::string("Password: ")) == -1) - return -1; - - std::string pass; - if (recv_line(pass) == -1) - return -1; - - TC_LOG_INFO("commands.ra", "Login attempt for user: %s", user.c_str()); - - if (check_access_level(user) == -1) - return -1; - - if (check_password(user, pass) == -1) - return -1; - - TC_LOG_INFO("commands.ra", "User login: %s", user.c_str()); - - return 0; -} - - -int RASocket::subnegotiate() -{ - char buf[1024]; - - ACE_Data_Block db(sizeof (buf), - ACE_Message_Block::MB_DATA, - buf, - 0, - 0, - ACE_Message_Block::DONT_DELETE, - 0); - - ACE_Message_Block message_block(&db, - ACE_Message_Block::DONT_DELETE, - 0); - - const size_t recv_size = message_block.space(); - - // Wait a maximum of 1000ms for negotiation packet - not all telnet clients may send it - ACE_Time_Value waitTime = ACE_Time_Value(1); - const ssize_t n = peer().recv(message_block.wr_ptr(), - recv_size, &waitTime); - - if (n <= 0) - return int(n); - - if (n >= 1024) - { - TC_LOG_DEBUG("commands.ra", "RASocket::subnegotiate: allocated buffer 1024 bytes was too small for negotiation packet, size: %u", uint32(n)); - return -1; - } - - buf[n] = '\0'; - - #ifdef _DEBUG - for (uint8 i = 0; i < n; ) - { - uint8 iac = buf[i]; - if (iac == 0xFF) // "Interpret as Command" (IAC) - { - uint8 command = buf[++i]; - std::stringstream ss; - switch (command) - { - case 0xFB: // WILL - ss << "WILL "; - break; - case 0xFC: // WON'T - ss << "WON'T "; - break; - case 0xFD: // DO - ss << "DO "; - break; - case 0xFE: // DON'T - ss << "DON'T "; - break; - default: - return -1; // not allowed - } - - uint8 param = buf[++i]; - ss << uint32(param); - TC_LOG_DEBUG("commands.ra", ss.str().c_str()); - } - ++i; - } - #endif - - //! Just send back end of subnegotiation packet - uint8 const reply[2] = {0xFF, 0xF0}; - -#ifdef MSG_NOSIGNAL - return int(peer().send(reply, 2, MSG_NOSIGNAL)); -#else - return int(peer().send(reply, 2)); -#endif // MSG_NOSIGNAL -} - -int RASocket::svc(void) -{ - //! Subnegotiation may differ per client - do not react on it - subnegotiate(); - - if (send("Authentication required\r\n") == -1) - return -1; - - if (authenticate() == -1) - { - (void) send("Authentication failed\r\n"); - return -1; - } - - // send motd - if (send(std::string(sWorld->GetMotd()) + "\r\n") == -1) - return -1; - - for (;;) - { - // show prompt - if (send("TC> ") == -1) - return -1; - - std::string line; - - if (recv_line(line) == -1) - return -1; - - if (process_command(line) == -1) - return -1; - } - - return 0; -} - -void RASocket::zprint(void* callbackArg, const char * szText) -{ - if (!szText || !callbackArg) - return; - - RASocket* socket = static_cast<RASocket*>(callbackArg); - size_t sz = strlen(szText); - - ACE_Message_Block* mb = new ACE_Message_Block(sz); - mb->copy(szText, sz); - - ACE_Time_Value tv = ACE_Time_Value::zero; - if (socket->putq(mb, &tv) == -1) - { - TC_LOG_DEBUG("commands.ra", "Failed to enqueue message, queue is full or closed. Error is %s", ACE_OS::strerror(errno)); - mb->release(); - } -} - -void RASocket::commandFinished(void* callbackArg, bool /*success*/) -{ - if (!callbackArg) - return; - - RASocket* socket = static_cast<RASocket*>(callbackArg); - - ACE_Message_Block* mb = new ACE_Message_Block(); - - mb->msg_type(ACE_Message_Block::MB_BREAK); - - // the message is 0 size control message to tell that command output is finished - // hence we don't put timeout, because it shouldn't increase queue size and shouldn't block - if (socket->putq(mb->duplicate()) == -1) - // getting here is bad, command can't be marked as complete - TC_LOG_DEBUG("commands.ra", "Failed to enqueue command end message. Error is %s", ACE_OS::strerror(errno)); - - mb->release(); - - socket->_commandExecuting = false; -} diff --git a/src/server/worldserver/RemoteAccess/RASocket.h b/src/server/worldserver/RemoteAccess/RASocket.h deleted file mode 100644 index 2cbb14b3578..00000000000 --- a/src/server/worldserver/RemoteAccess/RASocket.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/// \addtogroup Trinityd -/// @{ -/// \file - -#ifndef _RASOCKET_H -#define _RASOCKET_H - -#include "Common.h" - -#include <ace/Synch_Traits.h> -#include <ace/Svc_Handler.h> -#include <ace/SOCK_Stream.h> -#include <ace/SOCK_Acceptor.h> - -/// Remote Administration socket -class RASocket : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> -{ - public: - RASocket(); - virtual ~RASocket() { } - - virtual int svc() override; - virtual int open(void* = 0) override; - virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) override; - - private: - int recv_line(std::string& outLine); - int recv_line(ACE_Message_Block& buffer); - int process_command(const std::string& command); - int authenticate(); - int subnegotiate(); ///< Used by telnet protocol RFC 854 / 855 - int check_access_level(const std::string& user); - int check_password(const std::string& user, const std::string& pass); - int send(const std::string& line); - - static void zprint(void* callbackArg, const char* szText); - static void commandFinished(void* callbackArg, bool success); - - private: - uint8 _minLevel; ///< Minimum security level required to connect - ACE_Atomic_Op<ACE_Thread_Mutex, bool> _commandExecuting; -}; - -#endif - -/// @} |