mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Relay link improvements, considering changing it.
This commit is contained in:
@@ -283,7 +283,6 @@ bool EmuTCPConnection::LineOutQueuePush(char* line) {
|
||||
}
|
||||
#endif
|
||||
if(line[0] == '*') {
|
||||
printf("LineOutQueuePush %s\n", line);
|
||||
if (strcmp(line, "**PACKETMODE**") == 0) {
|
||||
MSendQueue.lock();
|
||||
safe_delete_array(sendbuf);
|
||||
|
||||
+8
-1
@@ -15,6 +15,12 @@ namespace EQ
|
||||
bool ipv6;
|
||||
};
|
||||
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(addrinfo));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
auto loop = EQ::EventLoop::Get().Handle();
|
||||
uv_getaddrinfo_t *resolver = new uv_getaddrinfo_t();
|
||||
memset(resolver, 0, sizeof(uv_getaddrinfo_t));
|
||||
@@ -47,8 +53,9 @@ namespace EQ
|
||||
delete baton;
|
||||
delete req;
|
||||
uv_freeaddrinfo(res);
|
||||
|
||||
cb(addr);
|
||||
}, addr.c_str(), port_str.c_str(), nullptr);
|
||||
}, addr.c_str(), port_str.c_str(), &hints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,6 +283,10 @@ std::string EQ::Net::Packet::ToString() const
|
||||
|
||||
std::string EQ::Net::Packet::ToString(size_t line_length) const
|
||||
{
|
||||
if (Length() == 0) {
|
||||
return fmt::format("{:0>5x} |", 0);
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
size_t lines = Length() / line_length;
|
||||
size_t i;
|
||||
|
||||
+131
-5
@@ -1,24 +1,52 @@
|
||||
#include "relay_link.h"
|
||||
#include "dns.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
#include <algorithm>
|
||||
#include "../md5.h"
|
||||
#include "../servertalk.h"
|
||||
|
||||
EQ::Net::RelayLink::RelayLink(const std::string &addr, int port, const std::string &identifier)
|
||||
EQ::Net::RelayLink::RelayLink(const std::string &addr, int port, const std::string &identifier, const std::string &password)
|
||||
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(250, true, std::bind(&EQ::Net::RelayLink::Connect, this))))
|
||||
{
|
||||
m_established = false;
|
||||
m_connecting = false;
|
||||
m_port = port;
|
||||
m_identifier = identifier;
|
||||
m_password = password;
|
||||
DNSLookup(addr, port, false, [this](const std::string &address) {
|
||||
m_addr = address;
|
||||
});
|
||||
|
||||
m_opcode_dispatch.insert(std::make_pair(ServerOP_ZAAuthFailed, std::bind(&RelayLink::OnAuthFailed, this, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
EQ::Net::RelayLink::~RelayLink()
|
||||
{
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::OnMessageType(uint16 opcode, std::function<void(const EQ::Net::Packet&p)> cb)
|
||||
{
|
||||
if (opcode != ServerOP_ZAAuthFailed) {
|
||||
m_opcode_dispatch.insert(std::make_pair(opcode, cb));
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::SendPacket(uint16 opcode, const EQ::Net::Packet &p)
|
||||
{
|
||||
EQ::Net::WritablePacket packet;
|
||||
packet.PutUInt32(0, p.Length() + 7);
|
||||
packet.PutInt8(4, 0);
|
||||
packet.PutUInt16(5, opcode);
|
||||
if(p.Length() > 0)
|
||||
packet.PutPacket(7, p);
|
||||
|
||||
if (m_connection) {
|
||||
m_connection->Write((const char*)packet.Data(), packet.Length());
|
||||
}
|
||||
else {
|
||||
m_packet_queue.push(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::Connect()
|
||||
{
|
||||
if (m_addr.length() == 0 || m_port == 0 || m_connection || m_connecting) {
|
||||
@@ -56,10 +84,17 @@ void EQ::Net::RelayLink::ProcessData(EQ::Net::TCPConnection *c, const unsigned c
|
||||
Log.OutF(Logs::General, Logs::Debug, "Process data:\n{0}", p.ToString());
|
||||
|
||||
if (m_established) {
|
||||
//process raw packet
|
||||
ProcessPacket(p);
|
||||
}
|
||||
else {
|
||||
auto msg = fmt::format("**PACKETMODE{0}**", m_identifier);
|
||||
std::string msg;
|
||||
if (m_identifier.compare("LOGIN") == 0) {
|
||||
msg = fmt::format("**PACKETMODE**\r");
|
||||
}
|
||||
else {
|
||||
msg = fmt::format("**PACKETMODE{0}**\r", m_identifier);
|
||||
}
|
||||
|
||||
std::string cmp_msg;
|
||||
if (p.GetInt8(0) == '*') {
|
||||
cmp_msg = p.GetString(0, msg.length());
|
||||
@@ -74,6 +109,7 @@ void EQ::Net::RelayLink::ProcessData(EQ::Net::TCPConnection *c, const unsigned c
|
||||
if (cmp_msg.compare(msg) == 0) {
|
||||
m_established = true;
|
||||
Log.OutF(Logs::General, Logs::Debug, "Established connection of type {0}", m_identifier);
|
||||
SendPassword();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,9 +118,79 @@ void EQ::Net::RelayLink::ProcessData(EQ::Net::TCPConnection *c, const unsigned c
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::ProcessPacket(const EQ::Net::Packet &p)
|
||||
{
|
||||
char *buffer = (char*)p.Data();
|
||||
m_data_buffer.insert(m_data_buffer.begin() + m_data_buffer.size(), buffer, buffer + p.Length());
|
||||
|
||||
ProcessBuffer();
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::ProcessBuffer()
|
||||
{
|
||||
size_t size = 7;
|
||||
size_t base = 0;
|
||||
size_t used = m_data_buffer.size();
|
||||
while ((used - base) >= size) {
|
||||
uint32 packet_size = *(uint32*)&m_data_buffer[base];
|
||||
uint8 packet_flags = *(uint8*)&m_data_buffer[base + 4];
|
||||
uint16 packet_opcode = *(uint16*)&m_data_buffer[base + 5];
|
||||
|
||||
if ((used - base) >= packet_size) {
|
||||
EQ::Net::ReadOnlyPacket p(&m_data_buffer[base], packet_size);
|
||||
|
||||
if (m_opcode_dispatch.count(packet_opcode) > 0) {
|
||||
auto &cb = m_opcode_dispatch[(int)packet_opcode];
|
||||
cb(p);
|
||||
}
|
||||
else {
|
||||
Log.OutF(Logs::General, Logs::Debug, "Unhandled packet of type {0:x}", packet_opcode);
|
||||
}
|
||||
|
||||
base += packet_size;
|
||||
}
|
||||
else {
|
||||
EQ::Net::WritablePacket p;
|
||||
|
||||
if (m_opcode_dispatch.count(packet_opcode) > 0) {
|
||||
auto &cb = m_opcode_dispatch[(int)packet_opcode];
|
||||
cb(p);
|
||||
}
|
||||
else {
|
||||
Log.OutF(Logs::General, Logs::Debug, "Unhandled packet of type {0:x}", packet_opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (used == base) {
|
||||
m_data_buffer.clear();
|
||||
}
|
||||
else {
|
||||
m_data_buffer.erase(m_data_buffer.begin(), m_data_buffer.begin() + base);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::ProcessQueue()
|
||||
{
|
||||
if (!m_connection)
|
||||
return;
|
||||
|
||||
while (!m_packet_queue.empty()) {
|
||||
auto &p = m_packet_queue.front();
|
||||
m_connection->Write((const char*)p.Data(), p.Length());
|
||||
m_packet_queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::SendIdentifier()
|
||||
{
|
||||
auto msg = fmt::format("**PACKETMODE{0}**\r", m_identifier);
|
||||
std::string msg;
|
||||
if (m_identifier.compare("LOGIN") == 0) {
|
||||
msg = fmt::format("**PACKETMODE**\r");
|
||||
}
|
||||
else {
|
||||
msg = fmt::format("**PACKETMODE{0}**\r", m_identifier);
|
||||
}
|
||||
EQ::Net::WritablePacket packet;
|
||||
packet.PutData(0, (void*)msg.c_str(), msg.length());
|
||||
SendInternal(packet);
|
||||
@@ -98,3 +204,23 @@ void EQ::Net::RelayLink::SendInternal(const EQ::Net::Packet &p)
|
||||
|
||||
m_connection->Write((const char*)p.Data(), p.Length());
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::SendPassword()
|
||||
{
|
||||
if (m_password.length() > 0) {
|
||||
char hash[16] = { 0 };
|
||||
MD5::Generate((const uchar*)m_password.c_str(), m_password.length(), (uchar*)&hash[0]);
|
||||
|
||||
EQ::Net::WritablePacket p;
|
||||
p.PutData(0, &hash[0], 16);
|
||||
SendPacket(ServerOP_ZAAuth, p);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::RelayLink::OnAuthFailed(const EQ::Net::Packet &p)
|
||||
{
|
||||
if (m_connection) {
|
||||
Log.OutF(Logs::General, Logs::Debug, "Authorization failed for server type {0}", m_identifier);
|
||||
m_connection->Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -2,8 +2,11 @@
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "packet.h"
|
||||
#include "../types.h"
|
||||
#include "../event/timer.h"
|
||||
#include "../event/event_loop.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
@@ -11,22 +14,36 @@ namespace EQ
|
||||
class RelayLink
|
||||
{
|
||||
public:
|
||||
RelayLink(const std::string &addr, int port, const std::string &identifier);
|
||||
RelayLink(const std::string &addr, int port, const std::string &identifier, const std::string &password);
|
||||
~RelayLink();
|
||||
|
||||
void OnMessageType(uint16 opcode, std::function<void(const EQ::Net::Packet &p)> cb);
|
||||
void SendPacket(uint16 opcode, const EQ::Net::Packet &p);
|
||||
bool Connected() const { return m_connection != nullptr; }
|
||||
std::string GetIP() const { return m_addr; }
|
||||
uint16 GetPort() const { return m_port; }
|
||||
private:
|
||||
void Connect();
|
||||
void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length);
|
||||
void ProcessPacket(const EQ::Net::Packet &p);
|
||||
void ProcessBuffer();
|
||||
void ProcessQueue();
|
||||
void SendIdentifier();
|
||||
void SendInternal(const EQ::Net::Packet &p);
|
||||
void SendPassword();
|
||||
void OnAuthFailed(const EQ::Net::Packet &p);
|
||||
|
||||
std::unique_ptr<EQ::Timer> m_timer;
|
||||
std::string m_addr;
|
||||
std::string m_identifier;
|
||||
std::string m_password;
|
||||
int m_port;
|
||||
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
|
||||
bool m_established;
|
||||
bool m_connecting;
|
||||
std::vector<char> m_data_buffer;
|
||||
std::map<uint16, std::function<void(const EQ::Net::Packet &p)>> m_opcode_dispatch;
|
||||
std::queue<EQ::Net::WritablePacket> m_packet_queue;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user