Skip to content

Commit

Permalink
Refactor RASocket::ProcessIncomingData
Browse files Browse the repository at this point in the history
Fixes the truncation of the last input character
Fixes the processing of several commands arrived in the same packet

refs cmangos/mangos-classic#185
closes cmangos/issues#877
  • Loading branch information
mityada authored and Phatcat committed Sep 10, 2016
1 parent 37e828c commit 01e867a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 47 deletions.
74 changes: 30 additions & 44 deletions src/mangosd/RASocket.cpp
Expand Up @@ -40,8 +40,6 @@ RASocket::RASocket(boost::asio::io_service &service, std::function<void(Socket *
m_secure(sConfig.GetBoolDefault("RA.Secure", true)), MaNGOS::Socket(service, closeHandler),
m_authLevel(AuthLevel::None), m_accountId(0), m_accountLevel(AccountTypes::SEC_PLAYER)
{
m_commandBuffer.reserve(InitialBufferSize);

if (sConfig.IsSet("RA.Stricted"))
{
sLog.outError("Deprecated config option RA.Stricted being used. Use RA.Restricted instead.");
Expand Down Expand Up @@ -76,48 +74,50 @@ bool RASocket::Open()
/// Read data from the network
bool RASocket::ProcessIncomingData()
{
DEBUG_LOG("RASocket::handle_input");
DEBUG_LOG("RASocket::ProcessIncomingData");

std::vector<char> buffer(ReadLengthRemaining());
std::string buffer;
buffer.resize(ReadLengthRemaining());
Read(&buffer[0], buffer.size());

bool completeCommand = false;
size_t newLine;
for (newLine = 0; newLine < buffer.size(); ++newLine)
static const std::string NEWLINE = "\n\r";

auto pos = 0;

while (pos != std::string::npos)
{
if (buffer[newLine] == '\r' || buffer[newLine] == '\n')
{
if (newLine > 0)
std::copy(buffer.cbegin(), buffer.cbegin() + newLine - 1, std::back_inserter(m_commandBuffer));
auto newLine = buffer.find_first_of(NEWLINE, pos);

m_input += buffer.substr(pos, newLine - pos);

pos = buffer.find_first_not_of(NEWLINE, newLine);

completeCommand = true;
if (newLine == std::string::npos)
break;
}
}

// no newline found? save what we have and return
if (newLine == buffer.size())
{
std::copy(buffer.cbegin(), buffer.cend(), std::back_inserter(m_commandBuffer));
return true;
if (!HandleInput())
return false;
}

return true;
}

bool RASocket::HandleInput()
{
auto const minLevel = static_cast<AccountTypes>(sConfig.GetIntDefault("RA.MinLevel", AccountTypes::SEC_ADMINISTRATOR));

switch (m_authLevel)
{
/// <ul> <li> If the input is '<username>'
case AuthLevel::None:
{
const std::string username(&m_commandBuffer[0], m_commandBuffer.size());

m_accountId = sAccountMgr.GetId(username);
m_accountId = sAccountMgr.GetId(m_input);

///- If the user is not found, deny access
if (!m_accountId)
{
Send("-No such user.\r\n");
sLog.outRALog("User %s does not exist.", username.c_str());
sLog.outRALog("User %s does not exist.", m_input.c_str());

if (m_secure)
return false;
Expand All @@ -133,7 +133,7 @@ bool RASocket::ProcessIncomingData()
if (m_accountLevel < minLevel)
{
Send("-Not enough privileges.\r\n");
sLog.outRALog("User %s has no privilege.", username.c_str());
sLog.outRALog("User %s has no privilege.", m_input.c_str());

if (m_secure)
return false;
Expand All @@ -155,9 +155,7 @@ bool RASocket::ProcessIncomingData()
case AuthLevel::HaveUsername:
{
// login+pass ok
const std::string pw(&m_commandBuffer[0], m_commandBuffer.size());

if (sAccountMgr.CheckPassword(m_accountId, pw))
if (sAccountMgr.CheckPassword(m_accountId, m_input))
{
m_authLevel = AuthLevel::Authenticated;

Expand All @@ -182,16 +180,14 @@ bool RASocket::ProcessIncomingData()
///<li> If user is logged, parse and execute the command
case AuthLevel::Authenticated:
{
const std::string command(&m_commandBuffer[0], m_commandBuffer.size());

if (command.length())
if (m_input.length())
{
sLog.outRALog("Got '%s' cmd.", command.c_str());
sLog.outRALog("Got '%s' cmd.", m_input.c_str());

if (command == "quit")
if (m_input == "quit")
return false;

sWorld.QueueCliCommand(new CliCommandHolder(m_accountId, m_accountLevel, command.c_str(),
sWorld.QueueCliCommand(new CliCommandHolder(m_accountId, m_accountLevel, m_input.c_str(),
[this] (const char *buffer) { this->Send(buffer); },
[this] (bool) { this->Send("mangos>"); }));
}
Expand All @@ -206,17 +202,7 @@ bool RASocket::ProcessIncomingData()
///</ul>
};

m_commandBuffer.clear();

// there might be additional data here, skip any newline characters first
for (; newLine < buffer.size(); ++newLine)
{
if (buffer[newLine] != '\r' && buffer[newLine] != '\n')
break;
}

if (newLine < buffer.size())
std::copy(buffer.cbegin() + newLine, buffer.cend(), std::back_inserter(m_commandBuffer));
m_input.clear();

return true;
}
Expand Down
5 changes: 2 additions & 3 deletions src/mangosd/RASocket.h
Expand Up @@ -42,18 +42,17 @@ class RASocket : public MaNGOS::Socket
Authenticated
};

static const int InitialBufferSize = 64;

const bool m_secure;
bool m_restricted;

std::vector<char> m_commandBuffer;
std::string m_input;

AuthLevel m_authLevel;
AccountTypes m_accountLevel;
uint32 m_accountId;

virtual bool ProcessIncomingData() override;
bool HandleInput();
void Send(const std::string &message);

public:
Expand Down

0 comments on commit 01e867a

Please sign in to comment.