mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
272 lines
5.7 KiB
C++
272 lines
5.7 KiB
C++
#include "console_server.h"
|
|
#include "../util/uuid.h"
|
|
#include "../net/packet.h"
|
|
#include "../eqemu_logsys.h"
|
|
#include "../servertalk.h"
|
|
#include "../rulesys.h"
|
|
#include <fmt/format.h>
|
|
|
|
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
|
|
{
|
|
m_parent = parent;
|
|
m_connection = connection;
|
|
m_uuid = EQ::Util::UUID::Generate().ToString();
|
|
m_cursor = 0;
|
|
memset(m_line, 0, MaxConsoleLineLength);
|
|
m_accept_messages = false;
|
|
m_user_id = 0;
|
|
m_admin = 0;
|
|
|
|
m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
|
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
|
|
m_connection->Start();
|
|
ClearBuffer();
|
|
|
|
auto addr = m_connection->RemoteIP();
|
|
|
|
SendLine(fmt::format("Establishing connection from: {0}:{1}", addr, m_connection->RemotePort()));
|
|
|
|
if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) {
|
|
SendLine("Connection established from localhost, assuming admin");
|
|
m_status = ConsoleStatusLoggedIn;
|
|
m_admin = 255;
|
|
SendPrompt();
|
|
}
|
|
else {
|
|
m_status = ConsoleStatusWaitingForLogin;
|
|
Send("Username: ");
|
|
}
|
|
}
|
|
|
|
EQ::Net::ConsoleServerConnection::~ConsoleServerConnection()
|
|
{
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::SendClear()
|
|
{
|
|
EQ::Net::DynamicPacket clear;
|
|
clear.PutUInt8(0, 0);
|
|
m_connection->Write((const char*)clear.Data(), clear.Length());
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::Send(const std::string &msg)
|
|
{
|
|
m_connection->Write(msg.c_str(), msg.length());
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::SendLine(const std::string &line)
|
|
{
|
|
Send(line);
|
|
SendNewLine();
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::SendNewLine()
|
|
{
|
|
EQ::Net::DynamicPacket newline;
|
|
newline.PutUInt8(0, 10);
|
|
newline.PutUInt8(1, 13);
|
|
m_connection->Write((const char*)newline.Data(), newline.Length());
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg)
|
|
{
|
|
if (!m_accept_messages) {
|
|
return;
|
|
}
|
|
|
|
if (m_cursor == 0) {
|
|
size_t len = m_user.length() + 2;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
Send("\x08");
|
|
}
|
|
|
|
SendLine(msg);
|
|
SendPrompt();
|
|
}
|
|
else {
|
|
std::string cmd(m_line, m_line + m_cursor);
|
|
|
|
size_t len = m_user.length() + 2 + cmd.length();
|
|
for (size_t i = 0; i < len; ++i) {
|
|
Send("\x08");
|
|
}
|
|
|
|
if (msg.length() < cmd.length()) {
|
|
Send(msg);
|
|
size_t blank_spaces = 2 + cmd.length() - msg.length();
|
|
|
|
for (size_t i = 0; i < blank_spaces; ++i) {
|
|
Send(" ");
|
|
}
|
|
|
|
SendNewLine();
|
|
}
|
|
else {
|
|
SendLine(msg);
|
|
}
|
|
|
|
SendPrompt();
|
|
Send(cmd);
|
|
}
|
|
}
|
|
|
|
bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function<void(void)> onTell) {
|
|
if (!m_accept_messages) {
|
|
return false;
|
|
}
|
|
|
|
switch (scm->chan_num) {
|
|
if (RuleB(Chat, ServerWideAuction)) {
|
|
case 4: {
|
|
QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (RuleB(Chat, ServerWideOOC)) {
|
|
case 5: {
|
|
QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message));
|
|
break;
|
|
}
|
|
}
|
|
|
|
case 6: {
|
|
QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message));
|
|
break;
|
|
}
|
|
|
|
case 7: {
|
|
QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message));
|
|
if (onTell) {
|
|
onTell();
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 11: {
|
|
QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message));
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz)
|
|
{
|
|
for (size_t i = 0; i < sz; ++i) {
|
|
unsigned char c = data[i];
|
|
|
|
switch (c) {
|
|
case 0:
|
|
m_cursor = 0;
|
|
break;
|
|
case 10: // \n
|
|
{
|
|
if (m_cursor > 0) {
|
|
std::string cmd(m_line, m_line + m_cursor);
|
|
ProcessCommand(cmd);
|
|
m_cursor = 0;
|
|
}
|
|
else {
|
|
ProcessCommand("");
|
|
}
|
|
}
|
|
break;
|
|
case 13: // \r
|
|
break;
|
|
case 8:
|
|
if (m_cursor > 0) {
|
|
m_cursor--;
|
|
}
|
|
break;
|
|
case 255:
|
|
//255 is always followed by a character
|
|
i++;
|
|
if (i < sz) {
|
|
unsigned char c = data[i];
|
|
|
|
if (c == 255) {
|
|
//Escaped 255
|
|
if (m_cursor < MaxConsoleLineLength && isprint(c)) {
|
|
m_line[m_cursor] = c;
|
|
m_cursor++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (c == 251 || c == 252 || c == 253 || c == 254) {
|
|
//Option code is always followed by an extra character
|
|
|
|
//We don't really care about negotiation tho.
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
break;
|
|
default:
|
|
if (m_cursor < MaxConsoleLineLength && isprint(c)) {
|
|
m_line[m_cursor] = c;
|
|
m_cursor++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::OnDisconnect(TCPConnection *c)
|
|
{
|
|
m_parent->ConnectionDisconnected(this);
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::ProcessCommand(const std::string &cmd)
|
|
{
|
|
if (m_status == ConsoleStatusWaitingForLogin) {
|
|
m_user = cmd;
|
|
m_status = ConsoleStatusWaitingForPassword;
|
|
Send("Password: ");
|
|
return;
|
|
}
|
|
|
|
if (m_status == ConsoleStatusWaitingForPassword) {
|
|
auto status = m_parent->m_login(m_user, cmd);
|
|
if (status.account_id == 0) {
|
|
m_status = ConsoleStatusFailedLogin;
|
|
SendLine("Access denied");
|
|
m_connection->Disconnect();
|
|
return;
|
|
}
|
|
|
|
if (status.status < ConsoleLoginStatus) {
|
|
m_status = ConsoleStatusFailedLogin;
|
|
SendLine("Access denied");
|
|
m_connection->Disconnect();
|
|
return;
|
|
}
|
|
|
|
m_user = status.account_name;
|
|
m_user_id = status.account_id;
|
|
m_admin = status.status;
|
|
m_status = ConsoleStatusLoggedIn;
|
|
SendPrompt();
|
|
return;
|
|
}
|
|
|
|
if (m_status == ConsoleStatusLoggedIn) {
|
|
m_parent->ProcessCommand(this, cmd);
|
|
}
|
|
}
|
|
|
|
void EQ::Net::ConsoleServerConnection::SendPrompt()
|
|
{
|
|
Send(fmt::format("{0}> ", m_user));
|
|
}
|