Relay link improvements, considering changing it.

This commit is contained in:
KimLS
2016-10-14 19:48:49 -07:00
parent 4ba0aa8e7f
commit 44b9c99781
10 changed files with 314 additions and 149 deletions
-1
View File
@@ -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
View File
@@ -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);
}
}
}
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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;
};
}
}