mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-04 04:12:25 +00:00
Proof of concept daybreak implementation using login
This commit is contained in:
parent
b62cc3b6fa
commit
4bbc22cc24
@ -77,7 +77,11 @@ SET(common_sources
|
|||||||
platform.cpp
|
platform.cpp
|
||||||
net/crc32.cpp
|
net/crc32.cpp
|
||||||
net/daybreak_connection.cpp
|
net/daybreak_connection.cpp
|
||||||
|
net/eqstream.cpp
|
||||||
net/packet.cpp
|
net/packet.cpp
|
||||||
|
patch/login_sod.cpp
|
||||||
|
patch/login_titanium.cpp
|
||||||
|
patch/patch.cpp
|
||||||
patches/patches.cpp
|
patches/patches.cpp
|
||||||
patches/sod.cpp
|
patches/sod.cpp
|
||||||
patches/sod_limits.cpp
|
patches/sod_limits.cpp
|
||||||
@ -220,7 +224,11 @@ SET(common_headers
|
|||||||
net/daybreak_connection.h
|
net/daybreak_connection.h
|
||||||
net/daybreak_structs.h
|
net/daybreak_structs.h
|
||||||
net/endian.h
|
net/endian.h
|
||||||
|
net/eqstream.h
|
||||||
net/packet.h
|
net/packet.h
|
||||||
|
patch/login_sod.h
|
||||||
|
patch/login_titanium.h
|
||||||
|
patch/patch.h
|
||||||
patches/patches.h
|
patches/patches.h
|
||||||
patches/sod.h
|
patches/sod.h
|
||||||
# patches/sod_itemfields.h
|
# patches/sod_itemfields.h
|
||||||
@ -275,13 +283,6 @@ SET(common_headers
|
|||||||
util/memory_stream.h
|
util/memory_stream.h
|
||||||
)
|
)
|
||||||
|
|
||||||
INCLUDE(CheckSymbolExists)
|
|
||||||
IF(WIN32)
|
|
||||||
check_symbol_exists(open io.h HAVE_OPEN)
|
|
||||||
ELSE()
|
|
||||||
check_symbol_exists(open fcntl.h HAVE_OPEN)
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
SOURCE_GROUP(Event FILES
|
SOURCE_GROUP(Event FILES
|
||||||
event/background_task.h
|
event/background_task.h
|
||||||
event/event_loop.h
|
event/event_loop.h
|
||||||
@ -295,10 +296,21 @@ SOURCE_GROUP(Net FILES
|
|||||||
net/daybreak_connection.h
|
net/daybreak_connection.h
|
||||||
net/daybreak_structs.h
|
net/daybreak_structs.h
|
||||||
net/endian.h
|
net/endian.h
|
||||||
|
net/eqstream.h
|
||||||
|
net/eqstream.cpp
|
||||||
net/packet.cpp
|
net/packet.cpp
|
||||||
net/packet.h
|
net/packet.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SOURCE_GROUP(Patch FILES
|
||||||
|
patch/login_sod.cpp
|
||||||
|
patch/login_sod.h
|
||||||
|
patch/login_titanium.cpp
|
||||||
|
patch/login_titanium.h
|
||||||
|
patch/patch.cpp
|
||||||
|
patch/patch.h
|
||||||
|
)
|
||||||
|
|
||||||
SOURCE_GROUP(Patches FILES
|
SOURCE_GROUP(Patches FILES
|
||||||
patches/patches.h
|
patches/patches.h
|
||||||
patches/sod.h
|
patches/sod.h
|
||||||
|
|||||||
@ -79,17 +79,6 @@ struct VarCache_Struct {
|
|||||||
|
|
||||||
class PTimerList;
|
class PTimerList;
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
|
||||||
#if _MSC_VER > 1700 // greater than 2012 (2013+)
|
|
||||||
# define _ISNAN_(a) std::isnan(a)
|
|
||||||
#else
|
|
||||||
# include <float.h>
|
|
||||||
# define _ISNAN_(a) _isnan(a)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
# define _ISNAN_(a) std::isnan(a)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class Database : public DBcore {
|
class Database : public DBcore {
|
||||||
public:
|
public:
|
||||||
Database();
|
Database();
|
||||||
|
|||||||
@ -1327,7 +1327,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
|||||||
if (rquery != ""){ results = QueryDatabase(rquery); }
|
if (rquery != ""){ results = QueryDatabase(rquery); }
|
||||||
|
|
||||||
/* Run Bind Home Convert */
|
/* Run Bind Home Convert */
|
||||||
if (pp->binds[4].zoneId < 999 && !_ISNAN_(pp->binds[4].x) && !_ISNAN_(pp->binds[4].y) && !_ISNAN_(pp->binds[4].z) && !_ISNAN_(pp->binds[4].heading)) {
|
if (pp->binds[4].zoneId < 999 && !std::isnan(pp->binds[4].x) && !std::isnan(pp->binds[4].y) && !std::isnan(pp->binds[4].z) && !std::isnan(pp->binds[4].heading)) {
|
||||||
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, 1)",
|
" VALUES (%u, %u, %u, %f, %f, %f, %f, 1)",
|
||||||
character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading);
|
character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading);
|
||||||
@ -1335,7 +1335,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Run Bind Convert */
|
/* Run Bind Convert */
|
||||||
if (pp->binds[0].zoneId < 999 && !_ISNAN_(pp->binds[0].x) && !_ISNAN_(pp->binds[0].y) && !_ISNAN_(pp->binds[0].z) && !_ISNAN_(pp->binds[0].heading)) {
|
if (pp->binds[0].zoneId < 999 && !std::isnan(pp->binds[0].x) && !std::isnan(pp->binds[0].y) && !std::isnan(pp->binds[0].z) && !std::isnan(pp->binds[0].heading)) {
|
||||||
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
rquery = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)"
|
||||||
" VALUES (%u, %u, %u, %f, %f, %f, %f, 0)",
|
" VALUES (%u, %u, %u, %f, %f, %f, %f, 0)",
|
||||||
character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading);
|
character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading);
|
||||||
|
|||||||
@ -41,6 +41,7 @@
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include "net\eqstream.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//for logsys
|
//for logsys
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
unsigned int CRC32Table[256] =
|
unsigned int CRC32EncodeTable[256] =
|
||||||
{
|
{
|
||||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||||
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
@ -74,7 +74,7 @@ int EQ::Crc32(const void * data, int size)
|
|||||||
int crc = 0xffffffff;
|
int crc = 0xffffffff;
|
||||||
auto buffer = (const uint8_t *)data;
|
auto buffer = (const uint8_t *)data;
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
crc = ((crc >> 8) & 0x00FFFFFFL) ^ CRC32Table[(crc ^ *&buffer[i]) & 0x000000FFL];
|
crc = ((crc >> 8) & 0x00FFFFFFL) ^ CRC32EncodeTable[(crc ^ *&buffer[i]) & 0x000000FFL];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ~crc;
|
return ~crc;
|
||||||
@ -84,12 +84,12 @@ int EQ::Crc32(const void * data, int size, int key)
|
|||||||
{
|
{
|
||||||
int crc = 0xffffffff;
|
int crc = 0xffffffff;
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
crc = ((crc >> 8) & 0x00FFFFFFL) ^ CRC32Table[(crc ^ ((key >> (i * 8)) & 0xff)) & 0x000000FFL];
|
crc = ((crc >> 8) & 0x00FFFFFFL) ^ CRC32EncodeTable[(crc ^ ((key >> (i * 8)) & 0xff)) & 0x000000FFL];
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buffer = (const uint8_t *)data;
|
auto buffer = (const uint8_t *)data;
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < size; ++i) {
|
||||||
crc = ((crc >> 8) & 0x00FFFFFFL) ^ CRC32Table[(crc ^ *&buffer[i]) & 0x000000FFL];
|
crc = ((crc >> 8) & 0x00FFFFFFL) ^ CRC32EncodeTable[(crc ^ *&buffer[i]) & 0x000000FFL];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ~crc;
|
return ~crc;
|
||||||
|
|||||||
115
common/net/eqstream.cpp
Normal file
115
common/net/eqstream.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#include "eqstream.h"
|
||||||
|
#include <eqemu_logsys.h>
|
||||||
|
|
||||||
|
EQ::Net::EQStreamManager::EQStreamManager(EQStreamManagerOptions &options) : m_daybreak(options.daybreak_options)
|
||||||
|
{
|
||||||
|
m_options = options;
|
||||||
|
|
||||||
|
m_daybreak.OnNewConnection(std::bind(&EQStreamManager::DaybreakNewConnection, this, std::placeholders::_1));
|
||||||
|
m_daybreak.OnConnectionStateChange(std::bind(&EQStreamManager::DaybreakConnectionStateChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
m_daybreak.OnPacketRecv(std::bind(&EQStreamManager::DaybreakPacketRecv, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Net::EQStreamManager::~EQStreamManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStreamManager::DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection)
|
||||||
|
{
|
||||||
|
std::shared_ptr<EQStream> stream(new EQStream(this, connection));
|
||||||
|
m_streams.insert(std::make_pair(connection, stream));
|
||||||
|
if (m_on_new_connection) {
|
||||||
|
m_on_new_connection(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStreamManager::DaybreakConnectionStateChange(std::shared_ptr<DaybreakConnection> connection, DbProtocolStatus from, DbProtocolStatus to)
|
||||||
|
{
|
||||||
|
auto iter = m_streams.find(connection);
|
||||||
|
if (iter != m_streams.end()) {
|
||||||
|
if (m_on_connection_state_change) {
|
||||||
|
m_on_connection_state_change(iter->second, from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to == EQ::Net::StatusDisconnected) {
|
||||||
|
m_streams.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStreamManager::DaybreakPacketRecv(std::shared_ptr<DaybreakConnection> connection, Packet &p)
|
||||||
|
{
|
||||||
|
auto iter = m_streams.find(connection);
|
||||||
|
if (iter != m_streams.end()) {
|
||||||
|
auto patch = iter->second->GetRegisteredPatch();
|
||||||
|
if (patch == nullptr && m_possible_patches.size() > 0) {
|
||||||
|
for (auto &pt : m_possible_patches) {
|
||||||
|
auto match = pt->TryIdentityMatch(p);
|
||||||
|
if (match == EQ::Patches::IdentityMatchSuccess) {
|
||||||
|
iter->second->RegisterPatch(pt.get());
|
||||||
|
patch = pt.get();
|
||||||
|
Log.OutF(Logs::General, Logs::Debug, "Identified patch with name {0}", pt->GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patch) {
|
||||||
|
EmuOpcode opcode;
|
||||||
|
EQ::Net::WritablePacket out;
|
||||||
|
patch->Decode(&p, opcode, out);
|
||||||
|
|
||||||
|
if (opcode == OP_Unknown) {
|
||||||
|
Log.OutF(Logs::General, Logs::Netcode, "Incoming packet was not handled because the opcode was not found.\n{0}", p.ToString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_on_packet_recv) {
|
||||||
|
m_on_packet_recv(iter->second, opcode, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.OutF(Logs::General, Logs::Netcode, "Incoming packet was not handled because we don't have a patch set.\n{0}", p.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Net::EQStream::EQStream(EQStreamManager *owner, std::shared_ptr<DaybreakConnection> connection)
|
||||||
|
{
|
||||||
|
m_owner = owner;
|
||||||
|
m_connection = connection;
|
||||||
|
m_patch = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Net::EQStream::~EQStream()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStream::QueuePacket(EmuOpcode type, Packet &p)
|
||||||
|
{
|
||||||
|
if (m_patch) {
|
||||||
|
EQ::Net::WritablePacket trans;
|
||||||
|
m_patch->Encode(m_connection, type, &p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStream::ResetStats()
|
||||||
|
{
|
||||||
|
m_connection->ResetStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStream::Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStream::QueuePacket(EQApplicationPacket *p)
|
||||||
|
{
|
||||||
|
EQ::Net::ReadOnlyPacket out(p->pBuffer, p->size);
|
||||||
|
QueuePacket(p->GetOpcode(), out);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Net::EQStream::FastQueuePacket(EQApplicationPacket **p)
|
||||||
|
{
|
||||||
|
QueuePacket(*p);
|
||||||
|
delete *p;
|
||||||
|
}
|
||||||
75
common/net/eqstream.h
Normal file
75
common/net/eqstream.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <patch/patch.h>
|
||||||
|
#include <eq_packet.h>
|
||||||
|
#include "daybreak_connection.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Net
|
||||||
|
{
|
||||||
|
struct EQStreamManagerOptions
|
||||||
|
{
|
||||||
|
EQStreamManagerOptions() {
|
||||||
|
compressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DaybreakConnectionManagerOptions daybreak_options;
|
||||||
|
bool compressed;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EQStream;
|
||||||
|
class EQStreamManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EQStreamManager(EQStreamManagerOptions &options);
|
||||||
|
~EQStreamManager();
|
||||||
|
|
||||||
|
void OnNewConnection(std::function<void(std::shared_ptr<EQStream>)> func) { m_on_new_connection = func; }
|
||||||
|
void OnConnectionStateChange(std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> func) { m_on_connection_state_change = func; }
|
||||||
|
void OnPacketRecv(std::function<void(std::shared_ptr<EQStream>, EmuOpcode, Packet &)> func) { m_on_packet_recv = func; }
|
||||||
|
|
||||||
|
void RegisterPotentialPatch(EQ::Patches::BasePatch *patch) { m_possible_patches.push_back(std::unique_ptr<EQ::Patches::BasePatch>(patch)); }
|
||||||
|
private:
|
||||||
|
EQStreamManagerOptions m_options;
|
||||||
|
DaybreakConnectionManager m_daybreak;
|
||||||
|
std::function<void(std::shared_ptr<EQStream>)> m_on_new_connection;
|
||||||
|
std::function<void(std::shared_ptr<EQStream>, DbProtocolStatus, DbProtocolStatus)> m_on_connection_state_change;
|
||||||
|
std::function<void(std::shared_ptr<EQStream>, EmuOpcode, Packet &)> m_on_packet_recv;
|
||||||
|
std::map<std::shared_ptr<DaybreakConnection>, std::shared_ptr<EQStream>> m_streams;
|
||||||
|
std::vector<std::unique_ptr<EQ::Patches::BasePatch>> m_possible_patches;
|
||||||
|
|
||||||
|
void DaybreakNewConnection(std::shared_ptr<DaybreakConnection> connection);
|
||||||
|
void DaybreakConnectionStateChange(std::shared_ptr<DaybreakConnection> connection, DbProtocolStatus from, DbProtocolStatus to);
|
||||||
|
void DaybreakPacketRecv(std::shared_ptr<DaybreakConnection> connection, Packet &p);
|
||||||
|
friend class EQStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EQStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EQStream(EQStreamManager *parent, std::shared_ptr<DaybreakConnection> connection);
|
||||||
|
~EQStream();
|
||||||
|
|
||||||
|
const std::string& RemoteEndpoint() const { return m_connection->RemoteEndpoint(); }
|
||||||
|
int RemotePort() const { return m_connection->RemotePort(); }
|
||||||
|
|
||||||
|
void QueuePacket(EmuOpcode type, Packet &p);
|
||||||
|
const DaybreakConnectionStats& GetStats() const { return m_connection->GetStats(); }
|
||||||
|
void ResetStats();
|
||||||
|
size_t GetRollingPing() const { return m_connection->GetRollingPing(); }
|
||||||
|
void Close();
|
||||||
|
void QueuePacket(EQApplicationPacket *p);
|
||||||
|
void FastQueuePacket(EQApplicationPacket **p);
|
||||||
|
|
||||||
|
void RegisterPatch(EQ::Patches::BasePatch *p) { m_patch = p; }
|
||||||
|
EQ::Patches::BasePatch *GetRegisteredPatch() { return m_patch; }
|
||||||
|
private:
|
||||||
|
EQStreamManager *m_owner;
|
||||||
|
std::shared_ptr<DaybreakConnection> m_connection;
|
||||||
|
EQ::Patches::BasePatch *m_patch;
|
||||||
|
friend class EQStreamManager;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
17
common/patch/login_sod.cpp
Normal file
17
common/patch/login_sod.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "login_sod.h"
|
||||||
|
|
||||||
|
EQ::Patches::LoginSoDPatch::LoginSoDPatch()
|
||||||
|
{
|
||||||
|
m_opcode_manager.reset(new RegularOpcodeManager());
|
||||||
|
if (!m_opcode_manager->LoadOpcodes("login_opcodes_sod.conf")) {
|
||||||
|
m_opcode_manager.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_signature.match_message_opcode = 0x01;
|
||||||
|
m_signature.match_message_size = 0;
|
||||||
|
m_message_size = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Patches::LoginSoDPatch::~LoginSoDPatch()
|
||||||
|
{
|
||||||
|
}
|
||||||
15
common/patch/login_sod.h
Normal file
15
common/patch/login_sod.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <patch/patch.h>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Patches
|
||||||
|
{
|
||||||
|
class LoginSoDPatch : public BasePatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LoginSoDPatch();
|
||||||
|
virtual ~LoginSoDPatch();
|
||||||
|
virtual std::string GetName() const { return "Login SoD+"; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
17
common/patch/login_titanium.cpp
Normal file
17
common/patch/login_titanium.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "login_titanium.h"
|
||||||
|
|
||||||
|
EQ::Patches::LoginTitaniumPatch::LoginTitaniumPatch()
|
||||||
|
{
|
||||||
|
m_opcode_manager.reset(new RegularOpcodeManager());
|
||||||
|
if (!m_opcode_manager->LoadOpcodes("login_opcodes_titanium.conf")) {
|
||||||
|
m_opcode_manager.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_signature.match_message_opcode = 0x01;
|
||||||
|
m_signature.match_message_size = 0;
|
||||||
|
m_message_size = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
EQ::Patches::LoginTitaniumPatch::~LoginTitaniumPatch()
|
||||||
|
{
|
||||||
|
}
|
||||||
15
common/patch/login_titanium.h
Normal file
15
common/patch/login_titanium.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <patch/patch.h>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Patches
|
||||||
|
{
|
||||||
|
class LoginTitaniumPatch : public BasePatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LoginTitaniumPatch();
|
||||||
|
virtual ~LoginTitaniumPatch();
|
||||||
|
virtual std::string GetName() const { return "Login Titanium"; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
107
common/patch/patch.cpp
Normal file
107
common/patch/patch.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "patch.h"
|
||||||
|
#include <eqemu_logsys.h>
|
||||||
|
|
||||||
|
EQ::Patches::IdentityMatchStatus EQ::Patches::BasePatch::TryIdentityMatch(const EQ::Net::Packet &p) const
|
||||||
|
{
|
||||||
|
if (p.Length() < m_message_size) {
|
||||||
|
return IdentityMatchFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
int raw_opcode = 0;
|
||||||
|
switch (m_message_size) {
|
||||||
|
case 1:
|
||||||
|
raw_opcode = *(uint8_t*)p.Data();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
raw_opcode = *(uint16_t*)p.Data();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return IdentityMatchFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_signature.match_message_opcode != raw_opcode) {
|
||||||
|
return IdentityMatchFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_signature.match_message_size > 0 && m_signature.match_message_size != p.Length() - m_message_size) {
|
||||||
|
return IdentityMatchFailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IdentityMatchSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Patches::BasePatch::Decode(const EQ::Net::Packet *in, EmuOpcode &opcode, EQ::Net::WritablePacket &out)
|
||||||
|
{
|
||||||
|
int raw_opcode = 0;
|
||||||
|
switch (m_message_size) {
|
||||||
|
case 1:
|
||||||
|
raw_opcode = *(uint8_t*)in->Data();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
raw_opcode = *(uint16_t*)in->Data();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
opcode = OP_Unknown;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opcode = m_opcode_manager->EQToEmu(raw_opcode);
|
||||||
|
if (opcode == OP_Unknown) {
|
||||||
|
out.PutData(0, (uint8_t*)in->Data() + m_message_size, in->Length() - m_message_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto decode_iter = m_decode.find(opcode);
|
||||||
|
if (decode_iter != m_decode.end()) {
|
||||||
|
EQ::Net::ReadOnlyPacket p((uint8_t*)in->Data() + m_message_size, in->Length() - m_message_size);
|
||||||
|
decode_iter->second(&p, opcode, out);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out.PutData(0, (uint8_t*)in->Data() + m_message_size, in->Length() - m_message_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Patches::BasePatch::Encode(std::shared_ptr<EQ::Net::DaybreakConnection> connection, EmuOpcode opcode, const EQ::Net::Packet *in)
|
||||||
|
{
|
||||||
|
auto encode_iter = m_encode.find(opcode);
|
||||||
|
if (encode_iter != m_encode.end()) {
|
||||||
|
encode_iter->second(connection, opcode, in);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SendPacket(connection, opcode, in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Patches::BasePatch::RegisterDecode(int protocol_number, DecodeStructFunction f)
|
||||||
|
{
|
||||||
|
m_decode.insert(std::make_pair(protocol_number, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Patches::BasePatch::RegisterEncode(EmuOpcode opcode, EncodeStructFunction f)
|
||||||
|
{
|
||||||
|
m_encode.insert(std::make_pair(opcode, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EQ::Patches::BasePatch::SendPacket(std::shared_ptr<EQ::Net::DaybreakConnection> connection, EmuOpcode opcode, const EQ::Net::Packet *p)
|
||||||
|
{
|
||||||
|
if (!m_opcode_manager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto raw_opcode = m_opcode_manager->EmuToEQ(opcode);
|
||||||
|
EQ::Net::WritablePacket out;
|
||||||
|
switch (m_message_size) {
|
||||||
|
case 1:
|
||||||
|
out.PutUInt8(0, (uint8_t)raw_opcode);
|
||||||
|
out.PutPacket(1, *p);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
out.PutUInt16(0, raw_opcode);
|
||||||
|
out.PutPacket(2, *p);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->QueuePacket(out);
|
||||||
|
}
|
||||||
53
common/patch/patch.h
Normal file
53
common/patch/patch.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <opcodemgr.h>
|
||||||
|
#include <net/packet.h>
|
||||||
|
#include <net/daybreak_connection.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace EQ
|
||||||
|
{
|
||||||
|
namespace Patches
|
||||||
|
{
|
||||||
|
enum IdentityMatchStatus
|
||||||
|
{
|
||||||
|
IdentityMatchFailure,
|
||||||
|
IdentityMatchSuccess
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Signature
|
||||||
|
{
|
||||||
|
int match_message_opcode;
|
||||||
|
size_t match_message_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BasePatch
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::function<void(const EQ::Net::Packet*, EmuOpcode&, EQ::Net::WritablePacket&)> DecodeStructFunction;
|
||||||
|
typedef std::function<void(std::shared_ptr<EQ::Net::DaybreakConnection>, EmuOpcode, const EQ::Net::Packet*)> EncodeStructFunction;
|
||||||
|
|
||||||
|
BasePatch() { }
|
||||||
|
virtual ~BasePatch() { }
|
||||||
|
virtual std::string GetName() const = 0;
|
||||||
|
|
||||||
|
IdentityMatchStatus TryIdentityMatch(const EQ::Net::Packet &p) const;
|
||||||
|
|
||||||
|
void Decode(const EQ::Net::Packet *in, EmuOpcode& opcode, EQ::Net::WritablePacket& out);
|
||||||
|
void Encode(std::shared_ptr<EQ::Net::DaybreakConnection> connection, EmuOpcode opcode, const EQ::Net::Packet *in);
|
||||||
|
|
||||||
|
void RegisterDecode(int protocol_number, DecodeStructFunction f);
|
||||||
|
void RegisterEncode(EmuOpcode opcode, EncodeStructFunction f);
|
||||||
|
protected:
|
||||||
|
void SendPacket(std::shared_ptr<EQ::Net::DaybreakConnection> connection, EmuOpcode opcode, const EQ::Net::Packet *p);
|
||||||
|
|
||||||
|
std::unique_ptr<OpcodeManager> m_opcode_manager;
|
||||||
|
std::map<int, DecodeStructFunction> m_decode;
|
||||||
|
std::map<EmuOpcode, EncodeStructFunction> m_encode;
|
||||||
|
Signature m_signature;
|
||||||
|
int m_message_size;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -297,7 +297,9 @@ inline DummyInt _ecvt_s(...) { return DummyInt(); }
|
|||||||
inline DummyInt isinf(...) { return DummyInt(); }
|
inline DummyInt isinf(...) { return DummyInt(); }
|
||||||
inline DummyInt _finite(...) { return DummyInt(); }
|
inline DummyInt _finite(...) { return DummyInt(); }
|
||||||
inline DummyInt isnan(...) { return DummyInt(); }
|
inline DummyInt isnan(...) { return DummyInt(); }
|
||||||
//inline DummyInt _isnan(...) { return DummyInt(); }
|
#ifndef _MSC_VER
|
||||||
|
inline DummyInt _isnan(...) { return DummyInt(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
// A helper function to suppress bogus "conditional expression is constant"
|
// A helper function to suppress bogus "conditional expression is constant"
|
||||||
// warnings.
|
// warnings.
|
||||||
|
|||||||
@ -41,7 +41,7 @@ ADD_EXECUTABLE(loginserver ${eqlogin_sources} ${eqlogin_headers})
|
|||||||
|
|
||||||
INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
INSTALL(TARGETS loginserver RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv)
|
TARGET_LINK_LIBRARIES(loginserver common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} libuv fmt)
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
TARGET_LINK_LIBRARIES(loginserver "ws2_32" "psapi" "iphlpapi" "userenv")
|
TARGET_LINK_LIBRARIES(loginserver "ws2_32" "psapi" "iphlpapi" "userenv")
|
||||||
|
|||||||
@ -18,13 +18,13 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "login_structures.h"
|
#include "login_structures.h"
|
||||||
#include "../common/misc_functions.h"
|
#include <misc_functions.h>
|
||||||
#include "../common/eqemu_logsys.h"
|
#include <eqemu_logsys.h>
|
||||||
|
|
||||||
extern EQEmuLogSys Log;
|
extern EQEmuLogSys Log;
|
||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
|
|
||||||
Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
|
Client::Client(std::shared_ptr<EQ::Net::EQStream> c, LSClientVersion v)
|
||||||
{
|
{
|
||||||
connection = c;
|
connection = c;
|
||||||
version = v;
|
version = v;
|
||||||
@ -34,82 +34,73 @@ Client::Client(std::shared_ptr<EQStream> c, LSClientVersion v)
|
|||||||
play_sequence_id = 0;
|
play_sequence_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::Process()
|
void Client::Process(EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
EQApplicationPacket *app = connection->PopPacket();
|
if(server.options.IsTraceOn())
|
||||||
while(app)
|
|
||||||
{
|
{
|
||||||
if(server.options.IsTraceOn())
|
Log.Out(Logs::General, Logs::Login_Server, "Application packet received from client (size %u)", app->Size());
|
||||||
{
|
}
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "Application packet received from client (size %u)", app->Size());
|
|
||||||
}
|
if(server.options.IsDumpInPacketsOn())
|
||||||
|
{
|
||||||
if(server.options.IsDumpInPacketsOn())
|
DumpPacket(app);
|
||||||
{
|
}
|
||||||
DumpPacket(app);
|
|
||||||
}
|
switch(app->GetOpcode())
|
||||||
|
{
|
||||||
switch(app->GetOpcode())
|
case OP_SessionReady:
|
||||||
{
|
{
|
||||||
case OP_SessionReady:
|
if(server.options.IsTraceOn())
|
||||||
{
|
{
|
||||||
if(server.options.IsTraceOn())
|
Log.Out(Logs::General, Logs::Login_Server, "Session ready received from client.");
|
||||||
{
|
}
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "Session ready received from client.");
|
Handle_SessionReady((const char*)app->pBuffer, app->Size());
|
||||||
}
|
break;
|
||||||
Handle_SessionReady((const char*)app->pBuffer, app->Size());
|
}
|
||||||
break;
|
case OP_Login:
|
||||||
}
|
{
|
||||||
case OP_Login:
|
if(app->Size() < 20)
|
||||||
{
|
{
|
||||||
if(app->Size() < 20)
|
Log.Out(Logs::General, Logs::Error, "Login received but it is too small, discarding.");
|
||||||
{
|
break;
|
||||||
Log.Out(Logs::General, Logs::Error, "Login received but it is too small, discarding.");
|
}
|
||||||
break;
|
|
||||||
}
|
if(server.options.IsTraceOn())
|
||||||
|
{
|
||||||
if(server.options.IsTraceOn())
|
Log.Out(Logs::General, Logs::Login_Server, "Login received from client.");
|
||||||
{
|
}
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "Login received from client.");
|
|
||||||
}
|
Handle_Login((const char*)app->pBuffer, app->Size());
|
||||||
|
break;
|
||||||
Handle_Login((const char*)app->pBuffer, app->Size());
|
}
|
||||||
break;
|
case OP_ServerListRequest:
|
||||||
}
|
{
|
||||||
case OP_ServerListRequest:
|
if(server.options.IsTraceOn())
|
||||||
{
|
{
|
||||||
if(server.options.IsTraceOn())
|
Log.Out(Logs::General, Logs::Login_Server, "Server list request received from client.");
|
||||||
{
|
}
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "Server list request received from client.");
|
|
||||||
}
|
SendServerListPacket();
|
||||||
|
break;
|
||||||
SendServerListPacket();
|
}
|
||||||
break;
|
case OP_PlayEverquestRequest:
|
||||||
}
|
{
|
||||||
case OP_PlayEverquestRequest:
|
if(app->Size() < sizeof(PlayEverquestRequest_Struct))
|
||||||
{
|
{
|
||||||
if(app->Size() < sizeof(PlayEverquestRequest_Struct))
|
Log.Out(Logs::General, Logs::Error, "Play received but it is too small, discarding.");
|
||||||
{
|
break;
|
||||||
Log.Out(Logs::General, Logs::Error, "Play received but it is too small, discarding.");
|
}
|
||||||
break;
|
|
||||||
}
|
Handle_Play((const char*)app->pBuffer);
|
||||||
|
break;
|
||||||
Handle_Play((const char*)app->pBuffer);
|
}
|
||||||
break;
|
default:
|
||||||
}
|
{
|
||||||
default:
|
char dump[64];
|
||||||
{
|
app->build_header_dump(dump);
|
||||||
char dump[64];
|
Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump);
|
||||||
app->build_header_dump(dump);
|
}
|
||||||
Log.Out(Logs::General, Logs::Error, "Recieved unhandled application packet from the client: %s.", dump);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete app;
|
|
||||||
app = connection->PopPacket();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::Handle_SessionReady(const char* data, unsigned int size)
|
void Client::Handle_SessionReady(const char* data, unsigned int size)
|
||||||
@ -187,13 +178,13 @@ void Client::Handle_Login(const char* data, unsigned int size)
|
|||||||
|
|
||||||
status = cs_logged_in;
|
status = cs_logged_in;
|
||||||
|
|
||||||
string entered_username;
|
std::string entered_username;
|
||||||
string entered_password_hash_result;
|
std::string entered_password_hash_result;
|
||||||
|
|
||||||
char *login_packet_buffer = nullptr;
|
char *login_packet_buffer = nullptr;
|
||||||
|
|
||||||
unsigned int db_account_id = 0;
|
unsigned int db_account_id = 0;
|
||||||
string db_account_password_hash;
|
std::string db_account_password_hash;
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
|
login_packet_buffer = server.eq_crypto->DecryptUsernamePassword(data, size, server.options.GetEncryptionMode());
|
||||||
@ -252,10 +243,8 @@ void Client::Handle_Login(const char* data, unsigned int size)
|
|||||||
|
|
||||||
server.client_manager->RemoveExistingClient(db_account_id);
|
server.client_manager->RemoveExistingClient(db_account_id);
|
||||||
|
|
||||||
in_addr in;
|
|
||||||
in.s_addr = connection->GetRemoteIP();
|
|
||||||
|
|
||||||
server.db->UpdateLSAccountData(db_account_id, string(inet_ntoa(in)));
|
server.db->UpdateLSAccountData(db_account_id, connection->RemoteEndpoint());
|
||||||
GenerateKey();
|
GenerateKey();
|
||||||
|
|
||||||
account_id = db_account_id;
|
account_id = db_account_id;
|
||||||
|
|||||||
@ -18,18 +18,14 @@
|
|||||||
#ifndef EQEMU_CLIENT_H
|
#ifndef EQEMU_CLIENT_H
|
||||||
#define EQEMU_CLIENT_H
|
#define EQEMU_CLIENT_H
|
||||||
|
|
||||||
#include "../common/global_define.h"
|
#include <global_define.h>
|
||||||
#include "../common/opcodemgr.h"
|
#include <net/eqstream.h>
|
||||||
#include "../common/eq_stream_type.h"
|
#include <random.h>
|
||||||
#include "../common/eq_stream_factory.h"
|
|
||||||
#include "../common/random.h"
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include "eq_crypto_api.h"
|
#include "eq_crypto_api.h"
|
||||||
#endif
|
#endif
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
enum LSClientVersion
|
enum LSClientVersion
|
||||||
{
|
{
|
||||||
cv_titanium,
|
cv_titanium,
|
||||||
@ -59,7 +55,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Constructor, sets our connection to c and version to v
|
* Constructor, sets our connection to c and version to v
|
||||||
*/
|
*/
|
||||||
Client(std::shared_ptr<EQStream> c, LSClientVersion v);
|
Client(std::shared_ptr<EQ::Net::EQStream> c, LSClientVersion v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
@ -69,7 +65,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Processes the client's connection and does various actions.
|
* Processes the client's connection and does various actions.
|
||||||
*/
|
*/
|
||||||
bool Process();
|
void Process(EQApplicationPacket *app);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends our reply to session ready packet.
|
* Sends our reply to session ready packet.
|
||||||
@ -109,12 +105,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Gets the account name of this client.
|
* Gets the account name of this client.
|
||||||
*/
|
*/
|
||||||
string GetAccountName() const { return account_name; }
|
std::string GetAccountName() const { return account_name; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the key generated at login for this client.
|
* Gets the key generated at login for this client.
|
||||||
*/
|
*/
|
||||||
string GetKey() const { return key; }
|
std::string GetKey() const { return key; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the server selected to be played on for this client.
|
* Gets the server selected to be played on for this client.
|
||||||
@ -129,19 +125,19 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Gets the connection for this client.
|
* Gets the connection for this client.
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<EQStream> GetConnection() { return connection; }
|
std::shared_ptr<EQ::Net::EQStream> GetConnection() { return connection; }
|
||||||
|
|
||||||
EQEmu::Random random;
|
EQEmu::Random random;
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<EQStream> connection;
|
std::shared_ptr<EQ::Net::EQStream> connection;
|
||||||
LSClientVersion version;
|
LSClientVersion version;
|
||||||
LSClientStatus status;
|
LSClientStatus status;
|
||||||
|
|
||||||
string account_name;
|
std::string account_name;
|
||||||
unsigned int account_id;
|
unsigned int account_id;
|
||||||
unsigned int play_server_id;
|
unsigned int play_server_id;
|
||||||
unsigned int play_sequence_id;
|
unsigned int play_sequence_id;
|
||||||
string key;
|
std::string key;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -17,148 +17,89 @@
|
|||||||
*/
|
*/
|
||||||
#include "client_manager.h"
|
#include "client_manager.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
|
#include <eqemu_logsys.h>
|
||||||
|
|
||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
extern bool run_server;
|
extern bool run_server;
|
||||||
|
|
||||||
#include "../common/eqemu_logsys.h"
|
|
||||||
extern EQEmuLogSys Log;
|
|
||||||
|
|
||||||
ClientManager::ClientManager()
|
ClientManager::ClientManager()
|
||||||
{
|
{
|
||||||
int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str());
|
EQ::Net::EQStreamManagerOptions titanium_opts;
|
||||||
titanium_stream = new EQStreamFactory(LoginStream, titanium_port);
|
titanium_opts.daybreak_options.port = atoi(server.config->GetVariable("Titanium", "port").c_str());
|
||||||
titanium_ops = new RegularOpcodeManager;
|
titanium_stream.reset(new EQ::Net::EQStreamManager(titanium_opts));
|
||||||
if(!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str()))
|
titanium_patch.reset(new EQ::Patches::LoginTitaniumPatch());
|
||||||
{
|
titanium_stream->RegisterPotentialPatch(titanium_patch.get());
|
||||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.",
|
|
||||||
server.config->GetVariable("Titanium", "opcodes").c_str());
|
|
||||||
run_server = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(titanium_stream->Open())
|
titanium_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
||||||
{
|
titanium_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionTitanium, this, std::placeholders::_1));
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on Titanium stream.");
|
titanium_stream->OnConnectionStateChange(std::bind(&ClientManager::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
}
|
titanium_stream->OnPacketRecv(std::bind(&ClientManager::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
else
|
|
||||||
{
|
EQ::Net::EQStreamManagerOptions sod_opts;
|
||||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open Titanium stream.");
|
sod_opts.daybreak_options.port = atoi(server.config->GetVariable("SoD", "port").c_str());
|
||||||
run_server = false;
|
sod_stream.reset(new EQ::Net::EQStreamManager(sod_opts));
|
||||||
}
|
sod_patch.reset(new EQ::Patches::LoginSoDPatch());
|
||||||
|
sod_stream->RegisterPotentialPatch(sod_patch.get());
|
||||||
|
|
||||||
|
sod_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
||||||
|
sod_stream->OnNewConnection(std::bind(&ClientManager::HandleNewConnectionSod, this, std::placeholders::_1));
|
||||||
|
sod_stream->OnConnectionStateChange(std::bind(&ClientManager::HandleConnectionChange, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
sod_stream->OnPacketRecv(std::bind(&ClientManager::HandlePacket, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
|
||||||
int sod_port = atoi(server.config->GetVariable("SoD", "port").c_str());
|
|
||||||
sod_stream = new EQStreamFactory(LoginStream, sod_port);
|
|
||||||
sod_ops = new RegularOpcodeManager;
|
|
||||||
if(!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str()))
|
|
||||||
{
|
|
||||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.",
|
|
||||||
server.config->GetVariable("SoD", "opcodes").c_str());
|
|
||||||
run_server = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sod_stream->Open())
|
|
||||||
{
|
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "ClientManager listening on SoD stream.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Out(Logs::General, Logs::Error, "ClientManager fatal error: couldn't open SoD stream.");
|
|
||||||
run_server = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientManager::~ClientManager()
|
ClientManager::~ClientManager()
|
||||||
{
|
{
|
||||||
if(titanium_stream)
|
|
||||||
{
|
|
||||||
titanium_stream->Close();
|
|
||||||
delete titanium_stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(titanium_ops)
|
|
||||||
{
|
|
||||||
delete titanium_ops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sod_stream)
|
|
||||||
{
|
|
||||||
sod_stream->Close();
|
|
||||||
delete sod_stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sod_ops)
|
|
||||||
{
|
|
||||||
delete sod_ops;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::Process()
|
void ClientManager::HandleNewConnectionTitanium(std::shared_ptr<EQ::Net::EQStream> connection)
|
||||||
{
|
{
|
||||||
ProcessDisconnect();
|
Log.OutF(Logs::General, Logs::Login_Server, "New Titanium client from {0}:{1}", connection->RemoteEndpoint(), connection->RemotePort());
|
||||||
std::shared_ptr<EQStream> cur = titanium_stream->Pop();
|
Client *c = new Client(connection, cv_titanium);
|
||||||
while(cur)
|
clients.push_back(std::unique_ptr<Client>(c));
|
||||||
{
|
}
|
||||||
struct in_addr in;
|
|
||||||
in.s_addr = cur->GetRemoteIP();
|
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "New Titanium client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
|
|
||||||
|
|
||||||
cur->SetOpcodeManager(&titanium_ops);
|
void ClientManager::HandleNewConnectionSod(std::shared_ptr<EQ::Net::EQStream> connection)
|
||||||
Client *c = new Client(cur, cv_titanium);
|
{
|
||||||
clients.push_back(c);
|
Log.OutF(Logs::General, Logs::Login_Server, "New SoD client from {0}:{1}", connection->RemoteEndpoint(), connection->RemotePort());
|
||||||
cur = titanium_stream->Pop();
|
Client *c = new Client(connection, cv_sod);
|
||||||
}
|
clients.push_back(std::unique_ptr<Client>(c));
|
||||||
|
}
|
||||||
|
|
||||||
cur = sod_stream->Pop();
|
void ClientManager::HandleConnectionChange(std::shared_ptr<EQ::Net::EQStream> connection, EQ::Net::DbProtocolStatus old_status, EQ::Net::DbProtocolStatus new_status)
|
||||||
while(cur)
|
{
|
||||||
{
|
if (new_status == EQ::Net::DbProtocolStatus::StatusDisconnected) {
|
||||||
struct in_addr in;
|
Log.OutF(Logs::General, Logs::Login_Server, "Client has been disconnected, removing {0}:{1}", connection->RemoteEndpoint(), connection->RemotePort());
|
||||||
in.s_addr = cur->GetRemoteIP();
|
auto iter = clients.begin();
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "New SoD client connection from %s:%d", inet_ntoa(in), ntohs(cur->GetRemotePort()));
|
while (iter != clients.end()) {
|
||||||
|
if ((*iter)->GetConnection() == connection) {
|
||||||
cur->SetOpcodeManager(&sod_ops);
|
clients.erase(iter);
|
||||||
Client *c = new Client(cur, cv_sod);
|
break;
|
||||||
clients.push_back(c);
|
}
|
||||||
cur = sod_stream->Pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
list<Client*>::iterator iter = clients.begin();
|
|
||||||
while(iter != clients.end())
|
|
||||||
{
|
|
||||||
if((*iter)->Process() == false)
|
|
||||||
{
|
|
||||||
Log.Out(Logs::General, Logs::Debug, "Client had a fatal error and had to be removed from the login.");
|
|
||||||
delete (*iter);
|
|
||||||
iter = clients.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::ProcessDisconnect()
|
void ClientManager::HandlePacket(std::shared_ptr<EQ::Net::EQStream> connection, EmuOpcode opcode, EQ::Net::Packet &p)
|
||||||
{
|
{
|
||||||
list<Client*>::iterator iter = clients.begin();
|
auto iter = clients.begin();
|
||||||
while(iter != clients.end())
|
while (iter != clients.end()) {
|
||||||
{
|
if ((*iter)->GetConnection() == connection) {
|
||||||
std::shared_ptr<EQStream> c = (*iter)->GetConnection();
|
EQApplicationPacket app(opcode, (unsigned char*)p.Data(), (uint32)p.Length());
|
||||||
if(c->CheckClosed())
|
(*iter)->Process(&app);
|
||||||
{
|
return;
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "Client disconnected from the server, removing client.");
|
|
||||||
delete (*iter);
|
|
||||||
iter = clients.erase(iter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::UpdateServerList()
|
void ClientManager::UpdateServerList()
|
||||||
{
|
{
|
||||||
list<Client*>::iterator iter = clients.begin();
|
auto iter = clients.begin();
|
||||||
while(iter != clients.end())
|
while(iter != clients.end())
|
||||||
{
|
{
|
||||||
(*iter)->SendServerListPacket();
|
(*iter)->SendServerListPacket();
|
||||||
@ -168,13 +109,12 @@ void ClientManager::UpdateServerList()
|
|||||||
|
|
||||||
void ClientManager::RemoveExistingClient(unsigned int account_id)
|
void ClientManager::RemoveExistingClient(unsigned int account_id)
|
||||||
{
|
{
|
||||||
list<Client*>::iterator iter = clients.begin();
|
auto iter = clients.begin();
|
||||||
while(iter != clients.end())
|
while(iter != clients.end())
|
||||||
{
|
{
|
||||||
if((*iter)->GetAccountID() == account_id)
|
if((*iter)->GetAccountID() == account_id)
|
||||||
{
|
{
|
||||||
Log.Out(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client.");
|
Log.Out(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client.");
|
||||||
delete (*iter);
|
|
||||||
iter = clients.erase(iter);
|
iter = clients.erase(iter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -188,12 +128,12 @@ Client *ClientManager::GetClient(unsigned int account_id)
|
|||||||
{
|
{
|
||||||
Client *cur = nullptr;
|
Client *cur = nullptr;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
list<Client*>::iterator iter = clients.begin();
|
auto iter = clients.begin();
|
||||||
while(iter != clients.end())
|
while(iter != clients.end())
|
||||||
{
|
{
|
||||||
if((*iter)->GetAccountID() == account_id)
|
if((*iter)->GetAccountID() == account_id)
|
||||||
{
|
{
|
||||||
cur = (*iter);
|
cur = (*iter).get();
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
++iter;
|
++iter;
|
||||||
|
|||||||
@ -18,14 +18,13 @@
|
|||||||
#ifndef EQEMU_CLIENTMANAGER_H
|
#ifndef EQEMU_CLIENTMANAGER_H
|
||||||
#define EQEMU_CLIENTMANAGER_H
|
#define EQEMU_CLIENTMANAGER_H
|
||||||
|
|
||||||
#include "../common/global_define.h"
|
#include <global_define.h>
|
||||||
#include "../common/opcodemgr.h"
|
#include <net/eqstream.h>
|
||||||
#include "../common/eq_stream_type.h"
|
#include <patch/login_sod.h>
|
||||||
#include "../common/eq_stream_factory.h"
|
#include <patch/login_titanium.h>
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client manager class, holds all the client objects and does basic processing.
|
* Client manager class, holds all the client objects and does basic processing.
|
||||||
@ -43,11 +42,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
~ClientManager();
|
~ClientManager();
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes every client in the internal list, removes them if necessary.
|
|
||||||
*/
|
|
||||||
void Process();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a new server list to every client.
|
* Sends a new server list to every client.
|
||||||
*/
|
*/
|
||||||
@ -63,17 +57,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
Client *GetClient(unsigned int account_id);
|
Client *GetClient(unsigned int account_id);
|
||||||
private:
|
private:
|
||||||
|
void HandleNewConnectionTitanium(std::shared_ptr<EQ::Net::EQStream> connection);
|
||||||
|
void HandleNewConnectionSod(std::shared_ptr<EQ::Net::EQStream> connection);
|
||||||
|
void HandleConnectionChange(std::shared_ptr<EQ::Net::EQStream> connection, EQ::Net::DbProtocolStatus old_status, EQ::Net::DbProtocolStatus new_status);
|
||||||
|
void HandlePacket(std::shared_ptr<EQ::Net::EQStream> connection, EmuOpcode opcode, EQ::Net::Packet &p);
|
||||||
|
|
||||||
/**
|
std::list<std::unique_ptr<Client>> clients;
|
||||||
* Processes disconnected clients, removes them if necessary.
|
std::unique_ptr<EQ::Net::EQStreamManager> titanium_stream;
|
||||||
*/
|
std::unique_ptr<EQ::Net::EQStreamManager> sod_stream;
|
||||||
void ProcessDisconnect();
|
std::unique_ptr<EQ::Patches::LoginTitaniumPatch> titanium_patch;
|
||||||
|
std::unique_ptr<EQ::Patches::LoginSoDPatch> sod_patch;
|
||||||
list<Client*> clients;
|
|
||||||
OpcodeManager *titanium_ops;
|
|
||||||
EQStreamFactory *titanium_stream;
|
|
||||||
OpcodeManager *sod_ops;
|
|
||||||
EQStreamFactory *sod_stream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
extern EQEmuLogSys Log;
|
extern EQEmuLogSys Log;
|
||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
|
|
||||||
DatabaseMySQL::DatabaseMySQL(string user, string pass, string host, string port, string name)
|
DatabaseMySQL::DatabaseMySQL(std::string user, std::string pass, std::string host, std::string port, std::string name)
|
||||||
{
|
{
|
||||||
this->user = user;
|
this->user = user;
|
||||||
this->pass = pass;
|
this->pass = pass;
|
||||||
@ -59,7 +59,7 @@ DatabaseMySQL::~DatabaseMySQL()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, unsigned int &id)
|
bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id)
|
||||||
{
|
{
|
||||||
if (!database)
|
if (!database)
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
|
|||||||
|
|
||||||
MYSQL_RES *res;
|
MYSQL_RES *res;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "SELECT LoginServerID, AccountPassword FROM " << server.options.GetAccountTable() << " WHERE AccountName = '";
|
query << "SELECT LoginServerID, AccountPassword FROM " << server.options.GetAccountTable() << " WHERE AccountName = '";
|
||||||
query << name;
|
query << name;
|
||||||
query << "'";
|
query << "'";
|
||||||
@ -97,7 +97,7 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(string name, string &password, u
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int &id)
|
bool DatabaseMySQL::CreateLoginData(std::string name, std::string &password, unsigned int &id)
|
||||||
{
|
{
|
||||||
if (!database) {
|
if (!database) {
|
||||||
return false;
|
return false;
|
||||||
@ -105,7 +105,7 @@ bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int
|
|||||||
|
|
||||||
MYSQL_RES *result;
|
MYSQL_RES *result;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
|
|
||||||
query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) ";
|
query << "INSERT INTO " << server.options.GetAccountTable() << " (AccountName, AccountPassword, AccountEmail, LastLoginDate, LastIPAddress) ";
|
||||||
query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); ";
|
query << " VALUES('" << name << "', '" << password << "', 'local_creation', NOW(), '127.0.0.1'); ";
|
||||||
@ -123,8 +123,8 @@ bool DatabaseMySQL::CreateLoginData(string name, string &password, unsigned int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, unsigned int &id, string &desc, unsigned int &list_id,
|
bool DatabaseMySQL::GetWorldRegistration(std::string long_name, std::string short_name, unsigned int &id, std::string &desc, unsigned int &list_id,
|
||||||
unsigned int &trusted, string &list_desc, string &account, string &password)
|
unsigned int &trusted, std::string &list_desc, std::string &account, std::string &password)
|
||||||
{
|
{
|
||||||
if (!database)
|
if (!database)
|
||||||
{
|
{
|
||||||
@ -137,7 +137,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
|||||||
unsigned long length;
|
unsigned long length;
|
||||||
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||||
escaped_short_name[length + 1] = 0;
|
escaped_short_name[length + 1] = 0;
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
|
query << "SELECT ifnull(WSR.ServerID,999999) AS ServerID, WSR.ServerTagDescription, ifnull(WSR.ServerTrusted,0) AS ServerTrusted, ifnull(SLT.ServerListTypeID,3) AS ServerListTypeID, ";
|
||||||
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
|
query << "SLT.ServerListTypeDescription, ifnull(WSR.ServerAdminID,0) AS ServerAdminID FROM " << server.options.GetWorldRegistrationTable();
|
||||||
query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID";
|
query << " AS WSR JOIN " << server.options.GetWorldServerTypeTable() << " AS SLT ON WSR.ServerListTypeID = SLT.ServerListTypeID";
|
||||||
@ -166,7 +166,7 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
|||||||
|
|
||||||
if (db_account_id > 0)
|
if (db_account_id > 0)
|
||||||
{
|
{
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable();
|
query << "SELECT AccountName, AccountPassword FROM " << server.options.GetWorldAdminRegistrationTable();
|
||||||
query << " WHERE ServerAdminID = " << db_account_id;
|
query << " WHERE ServerAdminID = " << db_account_id;
|
||||||
|
|
||||||
@ -199,14 +199,14 @@ bool DatabaseMySQL::GetWorldRegistration(string long_name, string short_name, un
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
|
void DatabaseMySQL::UpdateLSAccountData(unsigned int id, std::string ip_address)
|
||||||
{
|
{
|
||||||
if (!database)
|
if (!database)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "UPDATE " << server.options.GetAccountTable() << " SET LastIPAddress = '";
|
query << "UPDATE " << server.options.GetAccountTable() << " SET LastIPAddress = '";
|
||||||
query << ip_address;
|
query << ip_address;
|
||||||
query << "', LastLoginDate = now() where LoginServerID = ";
|
query << "', LastLoginDate = now() where LoginServerID = ";
|
||||||
@ -218,14 +218,14 @@ void DatabaseMySQL::UpdateLSAccountData(unsigned int id, string ip_address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string password, string email)
|
void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, std::string name, std::string password, std::string email)
|
||||||
{
|
{
|
||||||
if (!database)
|
if (!database)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "REPLACE " << server.options.GetAccountTable() << " SET LoginServerID = ";
|
query << "REPLACE " << server.options.GetAccountTable() << " SET LoginServerID = ";
|
||||||
query << id << ", AccountName = '" << name << "', AccountPassword = sha('";
|
query << id << ", AccountName = '" << name << "', AccountPassword = sha('";
|
||||||
query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email;
|
query << password << "'), AccountCreateDate = now(), AccountEmail = '" << email;
|
||||||
@ -237,7 +237,7 @@ void DatabaseMySQL::UpdateLSAccountInfo(unsigned int id, string name, string pas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, string ip_address)
|
void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, std::string long_name, std::string ip_address)
|
||||||
{
|
{
|
||||||
if (!database)
|
if (!database)
|
||||||
{
|
{
|
||||||
@ -248,7 +248,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
|
|||||||
unsigned long length;
|
unsigned long length;
|
||||||
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
|
length = mysql_real_escape_string(database, escaped_long_name, long_name.substr(0, 100).c_str(), long_name.substr(0, 100).length());
|
||||||
escaped_long_name[length + 1] = 0;
|
escaped_long_name[length + 1] = 0;
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '";
|
query << "UPDATE " << server.options.GetWorldRegistrationTable() << " SET ServerLastLoginDate = now(), ServerLastIPAddr = '";
|
||||||
query << ip_address;
|
query << ip_address;
|
||||||
query << "', ServerLongName = '";
|
query << "', ServerLongName = '";
|
||||||
@ -262,7 +262,7 @@ void DatabaseMySQL::UpdateWorldRegistration(unsigned int id, string long_name, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name, unsigned int &id)
|
bool DatabaseMySQL::CreateWorldRegistration(std::string long_name, std::string short_name, unsigned int &id)
|
||||||
{
|
{
|
||||||
if (!database)
|
if (!database)
|
||||||
{
|
{
|
||||||
@ -278,7 +278,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
|
|||||||
escaped_long_name[length + 1] = 0;
|
escaped_long_name[length + 1] = 0;
|
||||||
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
length = mysql_real_escape_string(database, escaped_short_name, short_name.substr(0, 100).c_str(), short_name.substr(0, 100).length());
|
||||||
escaped_short_name[length + 1] = 0;
|
escaped_short_name[length + 1] = 0;
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
|
query << "SELECT ifnull(max(ServerID),0) FROM " << server.options.GetWorldRegistrationTable();
|
||||||
|
|
||||||
if (mysql_query(database, query.str().c_str()) != 0)
|
if (mysql_query(database, query.str().c_str()) != 0)
|
||||||
@ -295,7 +295,7 @@ bool DatabaseMySQL::CreateWorldRegistration(string long_name, string short_name,
|
|||||||
id = atoi(row[0]) + 1;
|
id = atoi(row[0]) + 1;
|
||||||
mysql_free_result(res);
|
mysql_free_result(res);
|
||||||
|
|
||||||
stringstream query(stringstream::in | stringstream::out);
|
std::stringstream query(std::stringstream::in | std::stringstream::out);
|
||||||
query << "INSERT INTO " << server.options.GetWorldRegistrationTable() << " SET ServerID = " << id;
|
query << "INSERT INTO " << server.options.GetWorldRegistrationTable() << " SET ServerID = " << id;
|
||||||
query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name;
|
query << ", ServerLongName = '" << escaped_long_name << "', ServerShortName = '" << escaped_short_name;
|
||||||
query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''";
|
query << "', ServerListTypeID = 3, ServerAdminID = 0, ServerTrusted = 0, ServerTagDescription = ''";
|
||||||
|
|||||||
@ -199,7 +199,6 @@ int main()
|
|||||||
Log.Out(Logs::General, Logs::Login_Server, "Server Started.");
|
Log.Out(Logs::General, Logs::Login_Server, "Server Started.");
|
||||||
EQ::Timer timer(10, true, []() {
|
EQ::Timer timer(10, true, []() {
|
||||||
Timer::SetCurrentTime();
|
Timer::SetCurrentTime();
|
||||||
server.client_manager->Process();
|
|
||||||
server.server_manager->Process();
|
server.server_manager->Process();
|
||||||
timeout_manager.CheckTimeouts();
|
timeout_manager.CheckTimeouts();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -71,7 +71,7 @@ void ServerManager::Process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
if ((*iter)->Process() == false) {
|
if ((*iter)->Process() == false) {
|
||||||
Log.Out(Logs::General, Logs::World_Server, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
|
Log.Out(Logs::General, Logs::World_Server, "World server %s had a fatal error and had to be removed from the login.", (*iter)->GetLongName().c_str());
|
||||||
@ -86,7 +86,7 @@ void ServerManager::Process()
|
|||||||
|
|
||||||
void ServerManager::ProcessDisconnect()
|
void ServerManager::ProcessDisconnect()
|
||||||
{
|
{
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
EmuTCPConnection *connection = (*iter)->GetConnection();
|
EmuTCPConnection *connection = (*iter)->GetConnection();
|
||||||
if (!connection->Connected()) {
|
if (!connection->Connected()) {
|
||||||
@ -105,7 +105,7 @@ void ServerManager::ProcessDisconnect()
|
|||||||
|
|
||||||
WorldServer* ServerManager::GetServerByAddress(unsigned int address)
|
WorldServer* ServerManager::GetServerByAddress(unsigned int address)
|
||||||
{
|
{
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
if ((*iter)->GetConnection()->GetrIP() == address) {
|
if ((*iter)->GetConnection()->GetrIP() == address) {
|
||||||
return (*iter);
|
return (*iter);
|
||||||
@ -120,24 +120,23 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
|
|||||||
{
|
{
|
||||||
unsigned int packet_size = sizeof(ServerListHeader_Struct);
|
unsigned int packet_size = sizeof(ServerListHeader_Struct);
|
||||||
unsigned int server_count = 0;
|
unsigned int server_count = 0;
|
||||||
in_addr in;
|
std::string client_ip = c->GetConnection()->RemoteEndpoint();
|
||||||
in.s_addr = c->GetConnection()->GetRemoteIP();
|
|
||||||
string client_ip = inet_ntoa(in);
|
|
||||||
|
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
if ((*iter)->IsAuthorized() == false) {
|
if ((*iter)->IsAuthorized() == false) {
|
||||||
++iter;
|
++iter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in_addr in;
|
||||||
in.s_addr = (*iter)->GetConnection()->GetrIP();
|
in.s_addr = (*iter)->GetConnection()->GetrIP();
|
||||||
string world_ip = inet_ntoa(in);
|
std::string world_ip = inet_ntoa(in);
|
||||||
|
|
||||||
if (world_ip.compare(client_ip) == 0) {
|
if (world_ip.compare(client_ip) == 0) {
|
||||||
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
|
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
|
||||||
}
|
}
|
||||||
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
|
else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) {
|
||||||
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
|
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -171,13 +170,14 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in_addr in;
|
||||||
in.s_addr = (*iter)->GetConnection()->GetrIP();
|
in.s_addr = (*iter)->GetConnection()->GetrIP();
|
||||||
string world_ip = inet_ntoa(in);
|
std::string world_ip = inet_ntoa(in);
|
||||||
if (world_ip.compare(client_ip) == 0) {
|
if (world_ip.compare(client_ip) == 0) {
|
||||||
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
||||||
data_pointer += ((*iter)->GetLocalIP().size() + 1);
|
data_pointer += ((*iter)->GetLocalIP().size() + 1);
|
||||||
}
|
}
|
||||||
else if (client_ip.find(server.options.GetLocalNetwork()) != string::npos) {
|
else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) {
|
||||||
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
|
||||||
data_pointer += ((*iter)->GetLocalIP().size() + 1);
|
data_pointer += ((*iter)->GetLocalIP().size() + 1);
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c)
|
|||||||
|
|
||||||
void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id)
|
void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id)
|
||||||
{
|
{
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
bool found = false;
|
bool found = false;
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
if ((*iter)->GetRuntimeID() == server_id) {
|
if ((*iter)->GetRuntimeID() == server_id) {
|
||||||
@ -263,9 +263,9 @@ void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *ignore)
|
bool ServerManager::ServerExists(std::string l_name, std::string s_name, WorldServer *ignore)
|
||||||
{
|
{
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
if ((*iter) == ignore) {
|
if ((*iter) == ignore) {
|
||||||
++iter;
|
++iter;
|
||||||
@ -281,9 +281,9 @@ bool ServerManager::ServerExists(string l_name, string s_name, WorldServer *igno
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerManager::DestroyServerByName(string l_name, string s_name, WorldServer *ignore)
|
void ServerManager::DestroyServerByName(std::string l_name, std::string s_name, WorldServer *ignore)
|
||||||
{
|
{
|
||||||
list<WorldServer*>::iterator iter = world_servers.begin();
|
auto iter = world_servers.begin();
|
||||||
while (iter != world_servers.end()) {
|
while (iter != world_servers.end()) {
|
||||||
if ((*iter) == ignore) {
|
if ((*iter) == ignore) {
|
||||||
++iter;
|
++iter;
|
||||||
|
|||||||
@ -158,7 +158,9 @@ bool WorldServer::Process()
|
|||||||
if(utwr->response > 0)
|
if(utwr->response > 0)
|
||||||
{
|
{
|
||||||
per->Allowed = 1;
|
per->Allowed = 1;
|
||||||
SendClientAuth(c->GetConnection()->GetRemoteIP(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
|
|
||||||
|
std::string remote_ip = c->GetConnection()->RemoteEndpoint();
|
||||||
|
SendClientAuth((unsigned int)inet_addr(remote_ip.c_str()), c->GetAccountName(), c->GetKey(), c->GetAccountID());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(utwr->response)
|
switch(utwr->response)
|
||||||
@ -215,9 +217,9 @@ bool WorldServer::Process()
|
|||||||
if(is_server_trusted)
|
if(is_server_trusted)
|
||||||
{
|
{
|
||||||
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
|
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
|
||||||
string name;
|
std::string name;
|
||||||
string password;
|
std::string password;
|
||||||
string email;
|
std::string email;
|
||||||
name.assign(lsau->useraccount);
|
name.assign(lsau->useraccount);
|
||||||
password.assign(lsau->userpassword);
|
password.assign(lsau->userpassword);
|
||||||
email.assign(lsau->useremail);
|
email.assign(lsau->useremail);
|
||||||
@ -372,10 +374,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
|||||||
unsigned int s_id = 0;
|
unsigned int s_id = 0;
|
||||||
unsigned int s_list_type = 0;
|
unsigned int s_list_type = 0;
|
||||||
unsigned int s_trusted = 0;
|
unsigned int s_trusted = 0;
|
||||||
string s_desc;
|
std::string s_desc;
|
||||||
string s_list_desc;
|
std::string s_list_desc;
|
||||||
string s_acct_name;
|
std::string s_acct_name;
|
||||||
string s_acct_pass;
|
std::string s_acct_pass;
|
||||||
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
|
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
|
||||||
{
|
{
|
||||||
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
|
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
|
||||||
@ -424,10 +426,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
|||||||
unsigned int server_id = 0;
|
unsigned int server_id = 0;
|
||||||
unsigned int server_list_type = 0;
|
unsigned int server_list_type = 0;
|
||||||
unsigned int is_server_trusted = 0;
|
unsigned int is_server_trusted = 0;
|
||||||
string server_description;
|
std::string server_description;
|
||||||
string server_list_description;
|
std::string server_list_description;
|
||||||
string server_account_name;
|
std::string server_account_name;
|
||||||
string server_account_password;
|
std::string server_account_password;
|
||||||
|
|
||||||
|
|
||||||
if(server.db->GetWorldRegistration(
|
if(server.db->GetWorldRegistration(
|
||||||
@ -493,7 +495,7 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
|
|||||||
|
|
||||||
in_addr in;
|
in_addr in;
|
||||||
in.s_addr = connection->GetrIP();
|
in.s_addr = connection->GetrIP();
|
||||||
server.db->UpdateWorldRegistration(GetRuntimeID(), long_name, string(inet_ntoa(in)));
|
server.db->UpdateWorldRegistration(GetRuntimeID(), long_name, std::string(inet_ntoa(in)));
|
||||||
|
|
||||||
if(is_server_authorized)
|
if(is_server_authorized)
|
||||||
{
|
{
|
||||||
@ -508,7 +510,7 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
|
|||||||
server_status = s->status;
|
server_status = s->status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldServer::SendClientAuth(unsigned int ip, string account, string key, unsigned int account_id)
|
void WorldServer::SendClientAuth(unsigned int ip, std::string account, std::string key, unsigned int account_id)
|
||||||
{
|
{
|
||||||
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct));
|
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct));
|
||||||
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer;
|
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer;
|
||||||
@ -522,14 +524,14 @@ void WorldServer::SendClientAuth(unsigned int ip, string account, string key, un
|
|||||||
|
|
||||||
in_addr in;
|
in_addr in;
|
||||||
in.s_addr = ip; connection->GetrIP();
|
in.s_addr = ip; connection->GetrIP();
|
||||||
string client_address(inet_ntoa(in));
|
std::string client_address(inet_ntoa(in));
|
||||||
in.s_addr = connection->GetrIP();
|
in.s_addr = connection->GetrIP();
|
||||||
string world_address(inet_ntoa(in));
|
std::string world_address(inet_ntoa(in));
|
||||||
|
|
||||||
if (client_address.compare(world_address) == 0) {
|
if (client_address.compare(world_address) == 0) {
|
||||||
client_auth->local = 1;
|
client_auth->local = 1;
|
||||||
}
|
}
|
||||||
else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) {
|
else if (client_address.find(server.options.GetLocalNetwork()) != std::string::npos) {
|
||||||
client_auth->local = 1;
|
client_auth->local = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -64,7 +64,6 @@ namespace EQEmu
|
|||||||
#undef max
|
#undef max
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <float.h>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <float.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user