eqemu-server/loginserver/world_server_manager.cpp
Chris Miles 1a48add20e
[Loginserver] Modernize codebase (#4647)
* Beginning of cleanup

* More cleanup

* More cleanup

* Enc cleanup

* client manager cleanup

* client cleanup

* More cleanup

* More cleanup

* Cleanup

* More cleanup, account  context, account management

* Remove positional fmt bindings

* Use LoginAccountContext

* Update loginserver_webserver.cpp

* Remove comments

* Port CreateLoginServerAccount to repositories

* More cleanup

* More cleanup

* More cleanup

* More cleanup

* Remove a ton of functions

* More cleanup

* More cleanup

* More cleanup

* Cleanup SendClientAuthToWorld

* Consolidate world server logic

* Update login_accounts_repository.h

* Update login_accounts_repository.h

* Move api tokens to repositories

* Cleanup options

* Move everything else to repositories

* Update account_management.cpp

* uint64 account

* Update login_schema.sql

* Fix

* Update world_server.cpp

* auto
2025-02-06 12:47:02 -06:00

219 lines
5.9 KiB
C++

#include "world_server_manager.h"
#include "login_server.h"
#include "login_types.h"
#include <stdlib.h>
#include "../common/eqemu_logsys.h"
#include "../common/ip_util.h"
extern LoginServer server;
extern bool run_server;
WorldServerManager::WorldServerManager()
{
int listen_port = server.config.GetVariableInt("general", "listen_port", 5998);
m_server_connection = std::make_unique<EQ::Net::ServertalkServer>();
EQ::Net::ServertalkServerOptions opts;
opts.port = listen_port;
opts.ipv6 = false;
m_server_connection->Listen(opts);
LogInfo("Loginserver now listening on port [{}]", listen_port);
m_server_connection->OnConnectionIdentified(
"World", [this](std::shared_ptr<EQ::Net::ServertalkServerConnection> c) {
LogInfo(
"New World Server connection from remote_ip [{}] port [{}]",
c->Handle()->RemoteIP(),
c->Handle()->RemotePort()
);
auto iter = std::find_if(
m_world_servers.begin(), m_world_servers.end(),
[&](const std::unique_ptr<WorldServer> &s) {
return s->GetConnection()->Handle()->RemoteIP() == c->Handle()->RemoteIP() &&
s->GetConnection()->Handle()->RemotePort() == c->Handle()->RemotePort();
}
);
if (iter != m_world_servers.end()) {
LogInfo(
"World server already existed for remote_ip [{}] port [{}] removing existing connection.",
c->Handle()->RemoteIP(),
c->Handle()->RemotePort()
);
m_world_servers.erase(iter);
}
m_world_servers.push_back(std::make_unique<WorldServer>(c));
}
);
m_server_connection->OnConnectionRemoved(
"World", [this](std::shared_ptr<EQ::Net::ServertalkServerConnection> c) {
auto iter = std::find_if(
m_world_servers.begin(), m_world_servers.end(),
[&](const std::unique_ptr<WorldServer> &server) {
return server->GetConnection()->GetUUID() == c->GetUUID();
}
);
if (iter != m_world_servers.end()) {
LogInfo(
"World server ID [{}] long_name [{}] short_name [{}] has been disconnected, removing.",
(*iter)->GetServerId(),
(*iter)->GetServerLongName(),
(*iter)->GetServerShortName()
);
m_world_servers.erase(iter);
}
}
);
}
WorldServerManager::~WorldServerManager() = default;
std::unique_ptr<EQApplicationPacket> WorldServerManager::CreateServerListPacket(Client *client, uint32 sequence)
{
unsigned int server_count = 0;
in_addr in{};
in.s_addr = client->GetConnection()->GetRemoteIP();
std::string client_ip = inet_ntoa(in);
LogDebug("ServerManager::CreateServerListPacket via client address [{}]", client_ip);
for (const auto &world_server: m_world_servers) {
if (world_server->IsAuthorizedToList()) {
++server_count;
}
}
SerializeBuffer buf;
// LoginBaseMessage_Struct header
buf.WriteInt32(sequence);
buf.WriteInt8(0);
buf.WriteInt8(0);
buf.WriteInt32(0);
// LoginBaseReplyMessage_Struct
buf.WriteInt8(true); // success (no error)
buf.WriteInt32(0x65); // 101 "No Error" eqlsstr
buf.WriteString("");
// ServerListReply_Struct
buf.WriteInt32(server_count);
for (const auto &s: m_world_servers) {
if (!s->IsAuthorizedToList()) {
LogDebug(
"ServerManager::CreateServerListPacket | Server [{}] via IP [{}] is not authorized to be listed",
s->GetServerLongName(),
s->GetConnection()->Handle()->RemoteIP()
);
continue;
}
bool use_local_ip = false;
std::string world_ip = s->GetConnection()->Handle()->RemoteIP();
if (world_ip == client_ip || IpUtil::IsIpInPrivateRfc1918(client_ip)) {
use_local_ip = true;
}
LogDebug(
"CreateServerListPacket | Building list entry | Client [{}] IP [{}] Server Long Name [{}] Server IP [{}] ({})",
client->GetAccountName(),
client_ip,
s->GetServerLongName(),
use_local_ip ? s->GetLocalIP() : s->GetRemoteIP(),
use_local_ip ? "Local" : "Remote"
);
s->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion());
}
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
}
void WorldServerManager::SendUserLoginToWorldRequest(
unsigned int server_id,
unsigned int client_account_id,
const std::string &client_loginserver
)
{
auto iter = std::find_if(
m_world_servers.begin(), m_world_servers.end(),
[&](const std::unique_ptr<WorldServer> &server) {
return server->GetServerId() == server_id;
}
);
if (iter != m_world_servers.end()) {
EQ::Net::DynamicPacket outapp;
outapp.Resize(sizeof(UsertoWorldRequest_Struct));
auto *r = reinterpret_cast<UsertoWorldRequest_Struct *>(outapp.Data());
r->worldid = server_id;
r->lsaccountid = client_account_id;
strncpy(r->login, client_loginserver.c_str(), 64);
(*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp);
LogNetcode("[UsertoWorldRequest] [Size: {}]\n{}", outapp.Length(), outapp.ToString());
}
else {
LogError("Client requested a user to world but supplied an invalid id of {}", server_id);
}
}
bool WorldServerManager::DoesServerExist(
const std::string &server_long_name,
const std::string &server_short_name,
WorldServer *ignore
)
{
return std::any_of(
m_world_servers.begin(), m_world_servers.end(), [&](const std::unique_ptr<WorldServer> &s) {
return s.get() != ignore &&
s->GetServerLongName() == server_long_name &&
s->GetServerShortName() == server_short_name;
}
);
}
void WorldServerManager::DestroyServerByName(
std::string server_long_name,
std::string server_short_name,
WorldServer *ignore
)
{
std::erase_if(
m_world_servers, [&](const std::unique_ptr<WorldServer> &s) {
if (s.get() == ignore) {
return false;
}
if (s->GetServerLongName() == server_long_name &&
s->GetServerShortName() == server_short_name) {
s->GetConnection()->Handle()->Disconnect();
LogInfo(
"Removing world server ID [{}] long name [{}] short name [{}]",
s->GetServerId(),
server_long_name,
server_short_name
);
return true;
}
return false;
}
);
}
const std::list<std::unique_ptr<WorldServer>> &WorldServerManager::GetWorldServers() const
{
return m_world_servers;
}