Proof of concept daybreak implementation using login

This commit is contained in:
KimLS
2016-09-10 00:01:37 -07:00
parent b62cc3b6fa
commit 4bbc22cc24
25 changed files with 648 additions and 313 deletions
+4 -4
View File
@@ -1,7 +1,7 @@
#include "crc32.h"
#include <memory.h>
unsigned int CRC32Table[256] =
unsigned int CRC32EncodeTable[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
@@ -74,7 +74,7 @@ int EQ::Crc32(const void * data, int size)
int crc = 0xffffffff;
auto buffer = (const uint8_t *)data;
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;
@@ -84,12 +84,12 @@ int EQ::Crc32(const void * data, int size, int key)
{
int crc = 0xffffffff;
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;
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;
+115
View 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
View 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;
};
}
}