Console initial implementation

This commit is contained in:
KimLS 2017-04-09 20:17:48 -07:00
parent 3acd845a79
commit 18d28ae8d3
18 changed files with 1302 additions and 413 deletions

View File

@ -73,6 +73,8 @@ SET(common_sources
platform.cpp platform.cpp
event/event_loop.cpp event/event_loop.cpp
json/jsoncpp.cpp json/jsoncpp.cpp
net/console_server.cpp
net/console_server_connection.cpp
net/crc32.cpp net/crc32.cpp
net/daybreak_connection.cpp net/daybreak_connection.cpp
net/eqstream.cpp net/eqstream.cpp
@ -207,6 +209,8 @@ SET(common_headers
event/timer.h event/timer.h
json/json.h json/json.h
json/json-forwards.h json/json-forwards.h
net/console_server.h
net/console_server_connection.h
net/crc32.h net/crc32.h
net/daybreak_connection.h net/daybreak_connection.h
net/daybreak_structs.h net/daybreak_structs.h
@ -270,6 +274,10 @@ SOURCE_GROUP(Json FILES
) )
SOURCE_GROUP(Net FILES SOURCE_GROUP(Net FILES
net/console_server.cpp
net/console_server.h
net/console_server_connection.cpp
net/console_server_connection.h
net/crc32.cpp net/crc32.cpp
net/crc32.h net/crc32.h
net/daybreak_connection.cpp net/daybreak_connection.cpp

View File

@ -0,0 +1,78 @@
#include "console_server.h"
#include "../string_util.h"
#include <fmt/format.h>
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
{
m_server.reset(new EQ::Net::TCPServer());
m_server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
ConsoleServerConnection *c = new ConsoleServerConnection(this, connection);
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
});
}
EQ::Net::ConsoleServer::~ConsoleServer()
{
}
void EQ::Net::ConsoleServer::RegisterCall(const std::string &command, int status_required, const std::string& help_definition, ConsoleServerCallback fn)
{
m_commands[command] = { fn, status_required, help_definition };
}
void EQ::Net::ConsoleServer::RegisterLogin(ConsoleServerLoginCallback fn)
{
m_login = fn;
}
void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
{
auto iter = m_connections.find(c->GetUUID());
if (iter != m_connections.end()) {
m_connections.erase(iter);
}
}
void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd)
{
auto split = SplitString(cmd, ' ');
if (split.size() > 0) {
auto command = split[0];
ToLowerString(command);
if (command == "help" || command == "?") {
c->SendLine("Commands:");
for (auto &cmd_def : m_commands) {
if (cmd_def.second.status_required <= c->Admin()) {
auto display = fmt::format(" {0}", cmd_def.second.help_definition);
c->SendLine(display);
}
}
c->SendPrompt();
return;
}
split.erase(split.begin(), split.begin() + 1);
auto cmd_def = m_commands.find(command);
if (cmd_def != m_commands.end()) {
if (c->Admin() >= cmd_def->second.status_required) {
cmd_def->second.fn(c, command, split);
c->SendPrompt();
}
else {
c->SendLine(fmt::format("Access denied for command: {0}", command));
c->SendPrompt();
}
}
else {
c->SendLine(fmt::format("Command not found: {0}", command));
c->SendPrompt();
}
}
else {
c->SendPrompt();
}
}

View File

@ -0,0 +1,49 @@
#pragma once
#include "console_server_connection.h"
#include <functional>
#include <vector>
namespace EQ
{
namespace Net
{
struct ConsoleLoginStatus
{
int status;
int account_id;
std::string account_name;
};
class ConsoleServer
{
public:
typedef std::function<void(ConsoleServerConnection*, const std::string&, const std::vector<std::string>&)> ConsoleServerCallback;
typedef std::function<struct ConsoleLoginStatus(const std::string&, const std::string&)> ConsoleServerLoginCallback;
ConsoleServer(const std::string &addr, int port);
~ConsoleServer();
void RegisterCall(const std::string& command, int status_required, const std::string& help_definition, ConsoleServerCallback fn);
void RegisterLogin(ConsoleServerLoginCallback fn);
private:
void ConnectionDisconnected(ConsoleServerConnection *c);
void ProcessCommand(ConsoleServerConnection *c, const std::string& cmd);
std::unique_ptr<TCPServer> m_server;
std::map<std::string, std::unique_ptr<ConsoleServerConnection>> m_connections;
struct ConsoleServerCommand
{
ConsoleServerCallback fn;
int status_required;
std::string help_definition;
};
std::map<std::string, ConsoleServerCommand> m_commands;
ConsoleServerLoginCallback m_login;
friend class ConsoleServerConnection;
};
}
}

View File

@ -0,0 +1,221 @@
#include "console_server.h"
#include "../common/util/uuid.h"
#include "../common/net/packet.h"
#include "../common/eqemu_logsys.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);
}
}
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));
}

View File

@ -0,0 +1,63 @@
#pragma once
#include "tcp_server.h"
#include <memory>
#include <map>
namespace EQ
{
namespace Net
{
enum ConsoleConnectionStatus
{
ConsoleStatusWaitingForLogin,
ConsoleStatusWaitingForPassword,
ConsoleStatusLoggedIn,
ConsoleStatusFailedLogin
};
const int MaxConsoleLineLength = 512;
const int ConsoleLoginStatus = 50;
class ConsoleServer;
class ConsoleServerConnection
{
public:
ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection);
~ConsoleServerConnection();
std::string GetUUID() const { return m_uuid; }
void ClearBuffer() { m_cursor = 0; }
void Close() { m_connection->Disconnect(); }
void SendClear();
void Send(const std::string &msg);
void SendLine(const std::string &line);
void SendNewLine();
void SendPrompt();
ConsoleConnectionStatus Status() const { return m_status; }
std::string UserName() const { return m_user; }
int UserId() const { return m_user_id; }
int Admin() const { return m_admin; }
bool AcceptMessages() const { return m_accept_messages; }
void SetAcceptMessages(bool v) { m_accept_messages = v; }
void QueueMessage(const std::string &msg);
private:
void OnRead(TCPConnection* c, const unsigned char* data, size_t sz);
void OnDisconnect(TCPConnection* c);
void ProcessCommand(const std::string &cmd);
ConsoleServer *m_parent;
std::shared_ptr<TCPConnection> m_connection;
std::string m_uuid;
ConsoleConnectionStatus m_status;
std::string m_user;
int m_user_id;
int m_admin;
bool m_accept_messages;
size_t m_cursor;
char m_line[MaxConsoleLineLength];
};
}
}

View File

@ -15,6 +15,16 @@ EQ::Net::TCPServer::~TCPServer() {
} }
void EQ::Net::TCPServer::Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb) void EQ::Net::TCPServer::Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
{
if (ipv6) {
Listen("::", port, ipv6, cb);
}
else {
Listen("0.0.0.0", port, ipv6, cb);
}
}
void EQ::Net::TCPServer::Listen(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
{ {
if (m_socket) { if (m_socket) {
return; return;
@ -29,10 +39,10 @@ void EQ::Net::TCPServer::Listen(int port, bool ipv6, std::function<void(std::sha
sockaddr_storage iaddr; sockaddr_storage iaddr;
if (ipv6) { if (ipv6) {
uv_ip6_addr("::", port, (sockaddr_in6*)&iaddr); uv_ip6_addr(addr.c_str(), port, (sockaddr_in6*)&iaddr);
} }
else { else {
uv_ip4_addr("0.0.0.0", port, (sockaddr_in*)&iaddr); uv_ip4_addr(addr.c_str(), port, (sockaddr_in*)&iaddr);
} }
uv_tcp_bind(m_socket, (sockaddr*)&iaddr, 0); uv_tcp_bind(m_socket, (sockaddr*)&iaddr, 0);

View File

@ -13,6 +13,7 @@ namespace EQ
~TCPServer(); ~TCPServer();
void Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb); void Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
void Listen(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
void Close(); void Close();
void AddClient(uv_tcp_t *c); void AddClient(uv_tcp_t *c);

View File

@ -15,6 +15,7 @@
*/ */
#include "string_util.h" #include "string_util.h"
#include <algorithm>
#ifdef _WINDOWS #ifdef _WINDOWS
#include <windows.h> #include <windows.h>
@ -71,6 +72,132 @@ const std::string StringFormat(const char* format, ...)
return output; return output;
} }
std::vector<std::string> SplitString(const std::string &str, char delim) {
std::vector<std::string> ret;
std::stringstream ss(str);
std::string item;
while(std::getline(ss, item, delim)) {
ret.push_back(item);
}
return ret;
}
std::string EscapeString(const std::string &s) {
std::string ret;
size_t sz = s.length();
for(size_t i = 0; i < sz; ++i) {
char c = s[i];
switch(c) {
case '\x00':
ret += "\\x00";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\\':
ret += "\\\\";
break;
case '\'':
ret += "\\'";
break;
case '\"':
ret += "\\\"";
break;
case '\x1a':
ret += "\\x1a";
break;
default:
ret.push_back(c);
break;
}
}
return ret;
}
std::string EscapeString(const char *src, size_t sz) {
std::string ret;
for(size_t i = 0; i < sz; ++i) {
char c = src[i];
switch(c) {
case '\x00':
ret += "\\x00";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\\':
ret += "\\\\";
break;
case '\'':
ret += "\\'";
break;
case '\"':
ret += "\\\"";
break;
case '\x1a':
ret += "\\x1a";
break;
default:
ret.push_back(c);
break;
}
}
return ret;
}
bool StringIsNumber(const std::string &s) {
try {
auto r = stod(s);
return true;
}
catch (std::exception) {
return false;
}
}
void ToLowerString(std::string &s) {
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}
void ToUpperString(std::string &s) {
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
}
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim) {
std::string ret;
for (size_t i = 0; i < ar.size(); ++i) {
if (i != 0) {
ret += delim;
}
ret += ar[i];
}
return ret;
}
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string) {
auto index = string_subject.find_first_of(search_string);
while (index != std::string::npos) {
string_subject.replace(index, index + 1, replace_string);
index = string_subject.find_first_of(search_string);
}
}
//Const char based
// normal strncpy doesnt put a null term on copied strings, this one does // normal strncpy doesnt put a null term on copied strings, this one does
// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp // ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
char* strn0cpy(char* dest, const char* source, uint32 size) { char* strn0cpy(char* dest, const char* source, uint32 size) {
@ -311,91 +438,6 @@ const char *ConvertArrayF(float input, char *returnchar)
return returnchar; return returnchar;
} }
std::vector<std::string> SplitString(const std::string &str, char delim) {
std::vector<std::string> ret;
std::stringstream ss(str);
std::string item;
while(std::getline(ss, item, delim)) {
ret.push_back(item);
}
return ret;
}
std::string EscapeString(const std::string &s) {
std::string ret;
size_t sz = s.length();
for(size_t i = 0; i < sz; ++i) {
char c = s[i];
switch(c) {
case '\x00':
ret += "\\x00";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\\':
ret += "\\\\";
break;
case '\'':
ret += "\\'";
break;
case '\"':
ret += "\\\"";
break;
case '\x1a':
ret += "\\x1a";
break;
default:
ret.push_back(c);
break;
}
}
return ret;
}
std::string EscapeString(const char *src, size_t sz) {
std::string ret;
for(size_t i = 0; i < sz; ++i) {
char c = src[i];
switch(c) {
case '\x00':
ret += "\\x00";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\\':
ret += "\\\\";
break;
case '\'':
ret += "\\'";
break;
case '\"':
ret += "\\\"";
break;
case '\x1a':
ret += "\\x1a";
break;
default:
ret.push_back(c);
break;
}
}
return ret;
}
bool isAlphaNumeric(const char *text) bool isAlphaNumeric(const char *text)
{ {
for (unsigned int charIndex = 0; charIndex<strlen(text); charIndex++) { for (unsigned int charIndex = 0; charIndex<strlen(text); charIndex++) {
@ -407,11 +449,3 @@ bool isAlphaNumeric(const char *text)
return true; return true;
} }
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string) {
auto index = string_subject.find_first_of(search_string);
while (index != std::string::npos) {
string_subject.replace(index, index + 1, replace_string);
index = string_subject.find_first_of(search_string);
}
}

View File

@ -23,34 +23,34 @@
#include "types.h" #include "types.h"
//std::string based
const std::string StringFormat(const char* format, ...);
const std::string vStringFormat(const char* format, va_list args);
std::vector<std::string> SplitString(const std::string &s, char delim);
std::string EscapeString(const char *src, size_t sz);
std::string EscapeString(const std::string &s);
bool StringIsNumber(const std::string &s);
void ToLowerString(std::string &s);
void ToUpperString(std::string &s);
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim);
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
//const char based
bool atobool(const char* iBool); bool atobool(const char* iBool);
bool isAlphaNumeric(const char *text); bool isAlphaNumeric(const char *text);
bool strn0cpyt(char* dest, const char* source, uint32 size); bool strn0cpyt(char* dest, const char* source, uint32 size);
char *CleanMobName(const char *in, char *out); char *CleanMobName(const char *in, char *out);
char *RemoveApostrophes(const char *s); char *RemoveApostrophes(const char *s);
char* strn0cpy(char* dest, const char* source, uint32 size); char* strn0cpy(char* dest, const char* source, uint32 size);
const char *ConvertArray(int input, char *returnchar); const char *ConvertArray(int input, char *returnchar);
const char *ConvertArrayF(float input, char *returnchar); const char *ConvertArrayF(float input, char *returnchar);
const char *MakeLowerString(const char *source); const char *MakeLowerString(const char *source);
const std::string StringFormat(const char* format, ...);
const std::string vStringFormat(const char* format, va_list args);
int MakeAnyLenString(char** ret, const char* format, ...); int MakeAnyLenString(char** ret, const char* format, ...);
std::string EscapeString(const char *src, size_t sz);
std::string EscapeString(const std::string &s);
std::vector<std::string> SplitString(const std::string &s, char delim);
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...); uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
uint32 hextoi(const char* num); uint32 hextoi(const char* num);
uint64 hextoi64(const char* num); uint64 hextoi64(const char* num);
void MakeLowerString(const char *source, char *target); void MakeLowerString(const char *source, char *target);
void RemoveApostrophes(std::string &s); void RemoveApostrophes(std::string &s);
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
#endif #endif

View File

@ -20,6 +20,7 @@ SET(world_sources
web_interface_eqw.cpp web_interface_eqw.cpp
wguild_mgr.cpp wguild_mgr.cpp
world_config.cpp world_config.cpp
world_console_connection.cpp
worlddb.cpp worlddb.cpp
zonelist.cpp zonelist.cpp
zoneserver.cpp zoneserver.cpp
@ -47,6 +48,8 @@ SET(world_headers
web_interface_eqw.h web_interface_eqw.h
wguild_mgr.h wguild_mgr.h
world_config.h world_config.h
world_console_connection.h
world_tcp_connection.h
worlddb.h worlddb.h
zonelist.h zonelist.h
zoneserver.h zoneserver.h

View File

@ -1066,7 +1066,8 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
if (guild_mgr.GuildExists(cle->GuildID())) { if (guild_mgr.GuildExists(cle->GuildID())) {
snprintf(tmpguild, 36, " <%s>", guild_mgr.GetGuildName(cle->GuildID())); snprintf(tmpguild, 36, " <%s>", guild_mgr.GetGuildName(cle->GuildID()));
} else }
else
tmpguild[0] = 0; tmpguild[0] = 0;
if (cle->LFG()) if (cle->LFG())
@ -1132,6 +1133,8 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
AppendAnyLenString(&output, &outsize, &outlen, "\r\n"); AppendAnyLenString(&output, &outsize, &outlen, "\r\n");
else else
AppendAnyLenString(&output, &outsize, &outlen, "\n"); AppendAnyLenString(&output, &outsize, &outlen, "\n");
//console_list.SendConsoleWho(connection, to, admin, &output, &outsize, &outlen);
} }
if (output) if (output)
connection->SendEmoteMessageRaw(to, 0, 0, 10, output); connection->SendEmoteMessageRaw(to, 0, 0, 10, output);

View File

@ -7,6 +7,7 @@
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include "../common/servertalk.h" #include "../common/servertalk.h"
#include "../common/event/timer.h" #include "../common/event/timer.h"
#include "../common/net/console_server_connection.h"
#include <vector> #include <vector>
#include <string> #include <string>

View File

@ -1,103 +1,505 @@
#include "console.h" #include "console.h"
#include "../common/eqemu_config.h" #include "clientlist.h"
#include "../common/util/uuid.h" #include "login_server.h"
#include "../common/eqemu_logsys.h" #include "login_server_list.h"
#include "../common//net/packet.h" #include "world_config.h"
#include "world_console_connection.h"
#include "worlddb.h"
#include "zonelist.h"
#include "zoneserver.h"
#include "../common/string_util.h"
#include "../common/md5.h"
ConsoleConnection::ConsoleConnection(ConsoleServer *parent, std::shared_ptr<EQ::Net::TCPConnection> connection) extern ClientList client_list;
extern ZSList zoneserver_list;
extern LoginServerList loginserverlist;
struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string& username, const std::string& password) {
struct EQ::Net::ConsoleLoginStatus ret;
ret.account_id = database.CheckLogin(username.c_str(), password.c_str());
if (ret.account_id == 0) {
return ret;
}
char account_name[64];
database.GetAccountName(ret.account_id, account_name);
ret.account_name = account_name;
ret.status = database.CheckStatus(ret.account_id);
return ret;
}
void ConsoleNull(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
}
void ConsoleWhoami(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
connection->SendLine(fmt::format("You are logged in as '{0}'", connection->UserName()));
connection->SendLine(fmt::format("You are known as '*{0}'", connection->UserName()));
connection->SendLine(fmt::format("AccessLevel: '{0}'", connection->Admin()));
}
void ConsoleZoneStatus(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
WorldConsoleTCPConnection console_connection(connection);
zoneserver_list.SendZoneStatus(0, connection->Admin(), &console_connection);
}
void ConsoleWho(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
Who_All_Struct whom;
memset(&whom, 0, sizeof(whom));
whom.lvllow = 0xFFFF;
whom.lvlhigh = 0xFFFF;
whom.wclass = 0xFFFF;
whom.wrace = 0xFFFF;
whom.gmlookup = 0xFFFF;
for (auto &arg : args) {
if (strcasecmp(arg.c_str(), "gm") == 0) {
whom.gmlookup = 1;
}
else if (StringIsNumber(arg)) {
if (whom.lvllow == 0xFFFF) {
whom.lvllow = atoi(arg.c_str());
whom.lvlhigh = whom.lvllow;
}
else if (atoi(arg.c_str()) > int(whom.lvllow))
whom.lvlhigh = atoi(arg.c_str());
else
whom.lvllow = atoi(arg.c_str());
}
else {
strn0cpy(whom.whom, arg.c_str(), sizeof(whom.whom));
}
}
WorldConsoleTCPConnection console_connection(connection);
client_list.ConsoleSendWhoAll(0, connection->Admin(), &whom, &console_connection);
}
void ConsoleUptime(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
if (StringIsNumber(args[0]) && atoi(args[0].c_str()) > 0) {
auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct));
ServerUptime_Struct* sus = (ServerUptime_Struct*)pack->pBuffer;
snprintf(sus->adminname, sizeof(sus->adminname), "*%s", connection->UserName());
sus->zoneserverid = atoi(args[0].c_str());
ZoneServer* zs = zoneserver_list.FindByID(sus->zoneserverid);
if (zs)
zs->SendPacket(pack);
else
connection->SendLine("Zoneserver not found.");
delete pack;
}
else {
WorldConsoleTCPConnection console_connection(connection);
ZSList::ShowUpTime(&console_connection);
}
}
void ConsoleMd5(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
uint8 md5[16];
MD5::Generate((const uchar*)args[0].c_str(), strlen(args[0].c_str()), md5);
connection->SendLine(StringFormat("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7], md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]));
}
void ConsoleEmote(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 3) {
return;
}
auto join_args = args;
join_args.erase(join_args.begin(), join_args.begin() + 2);
if (strcasecmp(args[0].c_str(), "world") == 0)
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
else {
ZoneServer* zs = zoneserver_list.FindByName(args[0].c_str());
if (zs != 0)
zs->SendEmoteMessageRaw(0, 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
else
zoneserver_list.SendEmoteMessageRaw(args[0].c_str(), 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
}
}
void ConsoleAcceptMessages(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
connection->SendLine("Usage: acceptmessages [on/off]");
return;
}
if (strcasecmp(args[0].c_str(), "on") == 0)
connection->SetAcceptMessages(true);
else if (strcasecmp(args[0].c_str(), "off") == 0)
connection->SetAcceptMessages(false);
else
connection->SendLine("Usage: acceptmessages [on/off]");
}
void ConsoleTell(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 2) {
return;
}
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
std::string to = args[0];
auto join_args = args;
join_args.erase(join_args.begin(), join_args.begin() + 1);
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, JoinString(join_args, " ").c_str());
}
void ConsoleBroadcast(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, JoinString(args, " ").c_str());
}
void ConsoleGMSay(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, JoinString(args, " ").c_str());
}
void ConsoleOOC(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, JoinString(args, " ").c_str());
}
void ConsoleAuction(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, JoinString(args, " ").c_str());
}
void ConsoleKick(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
auto pack = new ServerPacket;
pack->opcode = ServerOP_KickPlayer;
pack->size = sizeof(ServerKickPlayer_Struct);
pack->pBuffer = new uchar[pack->size];
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer;
strcpy(skp->adminname, tmpname);
strcpy(skp->name, args[0].c_str());
skp->adminrank = connection->Admin();
zoneserver_list.SendPacket(pack);
delete pack;
}
void ConsoleLock(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
WorldConfig::LockWorld();
if (loginserverlist.Connected()) {
loginserverlist.SendStatus();
connection->SendLine("World locked.");
}
else {
connection->SendLine("World locked, but login server not connected.");
}
}
void ConsoleUnlock(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
WorldConfig::UnlockWorld();
if (loginserverlist.Connected()) {
loginserverlist.SendStatus();
connection->SendLine("World unlocked.");
}
else {
connection->SendLine("World unlocked, but login server not connected.");
}
}
void ConsoleZoneShutdown(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
connection->SendLine("Usage: zoneshutdown zoneshortname");
return;
}
if (args[0].length() == 0) {
connection->SendLine("Usage: zoneshutdown zoneshortname");
}
else {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
auto pack = new ServerPacket;
pack->size = sizeof(ServerZoneStateChange_struct);
pack->pBuffer = new uchar[pack->size];
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct));
ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *)pack->pBuffer;
pack->opcode = ServerOP_ZoneShutdown;
strcpy(s->adminname, tmpname);
if (StringIsNumber(args[0]))
s->ZoneServerID = atoi(args[0].c_str());
else
s->zoneid = database.GetZoneID(args[0].c_str());
ZoneServer* zs = 0;
if (s->ZoneServerID != 0)
zs = zoneserver_list.FindByID(s->ZoneServerID);
else if (s->zoneid != 0)
zs = zoneserver_list.FindByName(database.GetZoneName(s->zoneid));
else
connection->SendLine("Error: ZoneShutdown: neither ID nor name specified");
if (zs == 0)
connection->SendLine("Error: ZoneShutdown: zoneserver not found");
else
zs->SendPacket(pack);
delete pack;
}
}
void ConsoleZoneBootup(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 2) {
return;
}
if (args[1].length() == 0 || !StringIsNumber(args[0])) {
connection->SendLine("Usage: zonebootup ZoneServerID# zoneshortname");
}
else {
char tmpname[64];
tmpname[0] = '*';
strcpy(&tmpname[1], connection->UserName().c_str());
Log(Logs::Detail, Logs::World_Server, "Console ZoneBootup: %s, %s, %s", tmpname, args[1].c_str(), args[0].c_str());
if (args.size() > 2) {
zoneserver_list.SOPZoneBootup(tmpname, atoi(args[0].c_str()), args[1].c_str(), (bool)(strcasecmp(args[1].c_str(), "static") == 0));
}
else {
zoneserver_list.SOPZoneBootup(tmpname, atoi(args[0].c_str()), args[1].c_str(), false);
}
}
}
void ConsoleZoneLock(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 1) {
return;
}
if (strcasecmp(args[0].c_str(), "list") == 0) {
WorldConsoleTCPConnection console_connection(connection);
zoneserver_list.ListLockedZones(0, &console_connection);
}
else if (strcasecmp(args[0].c_str(), "lock") == 0 && connection->Admin() >= 101) {
if (args.size() < 2) {
return;
}
uint16 tmp = database.GetZoneID(args[1].c_str());
if (tmp) {
if (zoneserver_list.SetLockedZone(tmp, true))
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", database.GetZoneName(tmp));
else
connection->SendLine("Failed to change lock");
}
else
connection->SendLine("Usage: #zonelock lock [zonename]");
}
else if (strcasecmp(args[0].c_str(), "unlock") == 0 && connection->Admin() >= 101) {
if (args.size() < 2) {
return;
}
uint16 tmp = database.GetZoneID(args[1].c_str());
if (tmp) {
if (zoneserver_list.SetLockedZone(tmp, false))
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", database.GetZoneName(tmp));
else
connection->SendLine("Failed to change lock");
}
else
connection->SendLine("Usage: #zonelock unlock [zonename]");
}
else {
connection->SendLine("#zonelock sub-commands");
connection->SendLine(" list");
if (connection->Admin() >= 101) {
connection->SendLine(" lock [zonename]");
connection->SendLine(" unlock [zonename]");
}
}
}
void ConsoleFlag(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 2) {
return;
}
if (args[1].length() == 0 || !StringIsNumber(args[0]))
connection->SendLine("Usage: flag [status] [accountname]");
else
{ {
m_parent = parent; if (atoi(args[0].c_str()) > connection->Admin())
m_connection = connection; connection->SendLine("You cannot set people's status to higher than your own");
m_uuid = EQ::Util::UUID::Generate().ToString(); else if (!database.SetAccountStatus(args[1].c_str(), atoi(args[0].c_str())))
connection->SendLine("Unable to flag account!");
m_connection->OnRead(std::bind(&ConsoleConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); else
m_connection->OnDisconnect(std::bind(&ConsoleConnection::OnDisconnect, this, std::placeholders::_1)); connection->SendLine("Account Flaged");
m_connection->Start(); }
Clear();
} }
ConsoleConnection::~ConsoleConnection() void ConsoleSetPass(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() != 2) {
connection->SendLine("Format: setpass accountname password");
}
else {
int16 tmpstatus = 0;
uint32 tmpid = database.GetAccountIDByName(args[0].c_str(), &tmpstatus);
if (!tmpid)
connection->SendLine("Error: Account not found");
else if (tmpstatus > connection->Admin())
connection->SendLine("Cannot change password: Account's status is higher than yours");
else if (database.SetLocalPassword(tmpid, args[1].c_str()))
connection->SendLine("Password changed.");
else
connection->SendLine("Error changing password.");
}
}
void ConsoleVersion(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
connection->SendLine(StringFormat("Current version information."));
connection->SendLine(StringFormat(" %s", CURRENT_VERSION));
connection->SendLine(StringFormat(" Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME));
connection->SendLine(StringFormat(" Last modified on: %s", LAST_MODIFIED));
}
void ConsoleWorldShutdown(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() == 2) {
int32 time, interval;
if (StringIsNumber(args[0]) && StringIsNumber(args[1]) && ((time = atoi(args[0].c_str()))>0) && ((interval = atoi(args[1].c_str()))>0)) {
zoneserver_list.WorldShutDown(time, interval);
}
else {
connection->SendLine("Usage: worldshutdown [now] [disable] ([time] [interval])");
}
}
else if(args.size() == 1) {
if (strcasecmp(args[0].c_str(), "now") == 0) {
zoneserver_list.WorldShutDown(0, 0);
}
else if (strcasecmp(args[0].c_str(), "disable") == 0) {
connection->SendLine("<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
zoneserver_list.SendEmoteMessage(0, 0, 0, 15, "<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
zoneserver_list.shutdowntimer->Disable();
zoneserver_list.reminder->Disable();
}
else {
connection->SendLine("Usage: worldshutdown [now] [disable] ([time] [interval])");
}
}
else {
connection->SendLine("Usage: worldshutdown [now] [disable] ([time] [interval])");
}
}
void ConsoleIpLookup(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() > 0) {
WorldConsoleTCPConnection console_connection(connection);
client_list.SendCLEList(connection->Admin(), 0, &console_connection, args[0].c_str());
}
}
void ConsoleSignalCharByName(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
if (args.size() < 2) {
return;
}
connection->SendLine(StringFormat("Signal Sent to %s with ID %i", (char*) args[0].c_str(), atoi(args[1].c_str())));
uint32 message_len = strlen((char*) args[0].c_str()) + 1;
auto pack = new ServerPacket(ServerOP_CZSignalClientByName,
sizeof(CZClientSignalByName_Struct) + message_len);
CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer;
strn0cpy(CZSC->Name, (char*) args[0].c_str(), 64);
CZSC->data = atoi(args[1].c_str());
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
void ConsoleReloadWorld(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
connection->SendLine("Reloading World...");
auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
ReloadWorld_Struct* RW = (ReloadWorld_Struct*)pack->pBuffer;
RW->Option = 1;
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
void ConsoleQuit(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
connection->SendLine("Exiting...");
connection->Close();
}
void RegisterConsoleFunctions(std::unique_ptr<EQ::Net::ConsoleServer>& console)
{ {
} console->RegisterLogin(std::bind(CheckLogin, std::placeholders::_1, std::placeholders::_2));
console->RegisterCall("whoami", 50, "whoami", std::bind(ConsoleWhoami, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
void ConsoleConnection::Clear() console->RegisterCall("who", 50, "who", std::bind(ConsoleWho, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
{ console->RegisterCall("zonestatus", 50, "zonestatus", std::bind(ConsoleZoneStatus, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
EQ::Net::DynamicPacket clear; console->RegisterCall("uptime", 50, "uptime [zoneID#]", std::bind(ConsoleUptime, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
clear.PutUInt8(0, 0); console->RegisterCall("md5", 50, "md5", std::bind(ConsoleMd5, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->Write((const char*)clear.Data(), clear.Length()); console->RegisterCall("emote", 50, "emote [zonename or charname or world] [type] [message]", std::bind(ConsoleEmote, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
} console->RegisterCall("echo", 50, "echo [on/off]", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("acceptmessages", 50, "acceptmessages [on/off]", std::bind(ConsoleAcceptMessages, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
void ConsoleConnection::SendLine(const std::string &line) console->RegisterCall("tell", 50, "tell [name] [message]", std::bind(ConsoleTell, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
{ console->RegisterCall("broadcast", 50, "broadcast [message]", std::bind(ConsoleBroadcast, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->Write(line.c_str(), line.length()); console->RegisterCall("gmsay", 50, "gmsay [message]", std::bind(ConsoleGMSay, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
SendNewLine(); console->RegisterCall("ooc", 50, "ooc [message]", std::bind(ConsoleOOC, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
} console->RegisterCall("auction", 50, "auction [message]", std::bind(ConsoleAuction, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("kick", 150, "kick [charname]", std::bind(ConsoleKick, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
void ConsoleConnection::SendNewLine() console->RegisterCall("lock", 150, "lock", std::bind(ConsoleLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
{ console->RegisterCall("unlock", 150, "unlock", std::bind(ConsoleUnlock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
EQ::Net::DynamicPacket newline; console->RegisterCall("zoneshutdown", 150, "zoneshutdown [zonename or ZoneServerID]", std::bind(ConsoleZoneShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
newline.PutUInt8(0, 10); console->RegisterCall("zonebootup", 150, "zonebootup [ZoneServerID] [zonename]", std::bind(ConsoleZoneBootup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
newline.PutUInt8(1, 13); console->RegisterCall("zonelock", 150, "zonelock [list|lock|unlock] [zonename]", std::bind(ConsoleZoneLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_connection->Write((const char*)newline.Data(), newline.Length()); console->RegisterCall("flag", 200, "flag [status] [accountname]", std::bind(ConsoleFlag, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
} console->RegisterCall("setpass", 200, "setpass [accountname] [newpass]", std::bind(ConsoleSetPass, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("version", 50, "version", std::bind(ConsoleVersion, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
void ConsoleConnection::OnRead(EQ::Net::TCPConnection *c, const unsigned char *data, size_t sz) console->RegisterCall("worldshutdown", 200, "worldshutdown", std::bind(ConsoleWorldShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
{ console->RegisterCall("iplookup", 50, "IPLookup [name]", std::bind(ConsoleIpLookup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + sz); console->RegisterCall("lsreconnect", 50, "LSReconnect", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
ProcessReadBuffer(); console->RegisterCall("signalcharbyname", 50, "signalcharbyname charname ID", std::bind(ConsoleSignalCharByName, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
} console->RegisterCall("reloadworld", 200, "reloadworld", std::bind(ConsoleReloadWorld, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
console->RegisterCall("ping", 50, "ping", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
void ConsoleConnection::ProcessReadBuffer() console->RegisterCall("quit", 50, "quit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
{ console->RegisterCall("exit", 50, "exit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
size_t buffer_start = 0;
for (size_t i = 0; i < m_buffer.size(); ++i) {
char c = m_buffer[i];
switch (c) {
case 0:
//Clear buffer
break;
case 10:
case 13:
//New Line
break;
case 8:
//Backspace
break;
default:
break;
}
}
}
void ConsoleConnection::ProcessCommand(const std::string &cmd)
{
}
void ConsoleConnection::OnDisconnect(EQ::Net::TCPConnection *c)
{
m_parent->ConnectionDisconnected(this);
}
ConsoleServer::ConsoleServer()
{
auto config = EQEmuConfig::get();
m_server.reset(new EQ::Net::TCPServer());
m_server->Listen(config->TelnetTCPPort, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
ConsoleConnection *c = new ConsoleConnection(this, connection);
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleConnection>(c)));
});
}
ConsoleServer::~ConsoleServer()
{
}
void ConsoleServer::ConnectionDisconnected(ConsoleConnection *c)
{
auto iter = m_connections.find(c->GetUUID());
if (iter != m_connections.end()) {
m_connections.erase(iter);
}
} }

View File

@ -1,45 +1,5 @@
#pragma once #pragma once
#include "../common/net/tcp_server.h" #include "../common/net/console_server.h"
#include "../common/event/timer.h"
#include <map>
#include <vector>
class ConsoleServer; void RegisterConsoleFunctions(std::unique_ptr<EQ::Net::ConsoleServer> &console);
class ConsoleConnection
{
public:
ConsoleConnection(ConsoleServer *parent, std::shared_ptr<EQ::Net::TCPConnection> connection);
~ConsoleConnection();
std::string GetUUID() const { return m_uuid; }
void Clear();
void SendLine(const std::string &line);
void SendNewLine();
private:
void OnRead(EQ::Net::TCPConnection* c, const unsigned char* data, size_t sz);
void ProcessReadBuffer();
void ProcessCommand(const std::string& cmd);
void OnDisconnect(EQ::Net::TCPConnection* c);
ConsoleServer *m_parent;
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
std::string m_uuid;
std::vector<char> m_buffer;
};
class ConsoleServer
{
public:
ConsoleServer();
~ConsoleServer();
void ConnectionDisconnected(ConsoleConnection *c);
private:
std::unique_ptr<EQ::Net::TCPServer> m_server;
std::map<std::string, std::unique_ptr<ConsoleConnection>> m_connections;
friend class ConsoleConnection;
};

View File

@ -83,7 +83,6 @@ union semun {
#include "web_interface.h" #include "web_interface.h"
#include "console.h" #include "console.h"
#include "../common/net/tcp_server.h"
#include "../common/net/servertalk_server.h" #include "../common/net/servertalk_server.h"
ClientList client_list; ClientList client_list;
@ -376,10 +375,11 @@ int main(int argc, char** argv) {
database.LoadCharacterCreateAllocations(); database.LoadCharacterCreateAllocations();
database.LoadCharacterCreateCombos(); database.LoadCharacterCreateCombos();
std::unique_ptr<ConsoleServer> console; std::unique_ptr<EQ::Net::ConsoleServer> console;
if (Config->TelnetEnabled) { if (Config->TelnetEnabled) {
Log(Logs::General, Logs::World_Server, "Console (TCP) listener started."); Log(Logs::General, Logs::World_Server, "Console (TCP) listener started.");
console.reset(new ConsoleServer()); console.reset(new EQ::Net::ConsoleServer(Config->TelnetIP, Config->TelnetTCPPort));
RegisterConsoleFunctions(console);
} }
std::unique_ptr<EQ::Net::ServertalkServer> server_connection; std::unique_ptr<EQ::Net::ServertalkServer> server_connection;

View File

@ -0,0 +1,19 @@
#include "world_console_connection.h"
#include <string.h>
#include <stdarg.h>
void WorldConsoleTCPConnection::SendEmoteMessage(const char *to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char *message, ...)
{
va_list argptr;
char buffer[1024];
va_start(argptr, message);
vsnprintf(buffer, sizeof(buffer), message, argptr);
va_end(argptr);
SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer);
}
void WorldConsoleTCPConnection::SendEmoteMessageRaw(const char *to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char *message)
{
m_connection->SendLine(message);
}

View File

@ -0,0 +1,36 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2017 EQEMu Development Team (http://eqemu.org)
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; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#pragma once
#include "world_tcp_connection.h"
#include "../common/net/console_server_connection.h"
class WorldConsoleTCPConnection : public WorldTCPConnection
{
public:
WorldConsoleTCPConnection(EQ::Net::ConsoleServerConnection *c) { m_connection = c; }
virtual ~WorldConsoleTCPConnection() { }
virtual void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
virtual void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message);
virtual inline bool IsConsole() { return true; }
virtual inline bool IsZoneServer() { return false; }
private:
EQ::Net::ConsoleServerConnection *m_connection;
};

View File

@ -481,10 +481,11 @@ int main(int argc, char** argv) {
worldwasconnected = true; worldwasconnected = true;
} }
else { else {
if (worldwasconnected && is_zone_loaded) if (worldwasconnected && is_zone_loaded) {
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost");
worldwasconnected = false; worldwasconnected = false;
} }
}
if (is_zone_loaded) { if (is_zone_loaded) {
{ {