mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Legacy connection wip
This commit is contained in:
@@ -72,11 +72,13 @@ SET(common_sources
|
||||
worldconn.cpp
|
||||
xml_parser.cpp
|
||||
platform.cpp
|
||||
event/event_loop.cpp
|
||||
net/crc32.cpp
|
||||
net/daybreak_connection.cpp
|
||||
net/eqstream.cpp
|
||||
net/packet.cpp
|
||||
net/servertalk_client_connection.cpp
|
||||
net/servertalk_legacy_client_connection.cpp
|
||||
net/servertalk_server.cpp
|
||||
net/servertalk_server_connection.cpp
|
||||
net/tcp_connection.cpp
|
||||
@@ -224,6 +226,7 @@ SET(common_headers
|
||||
net/eqstream.h
|
||||
net/packet.h
|
||||
net/servertalk_client_connection.h
|
||||
net/servertalk_legacy_client_connection.h
|
||||
net/servertalk_common.h
|
||||
net/servertalk_server.h
|
||||
net/servertalk_server_connection.h
|
||||
@@ -286,6 +289,7 @@ SET(common_headers
|
||||
|
||||
SOURCE_GROUP(Event FILES
|
||||
event/background_task.h
|
||||
event/event_loop.cpp
|
||||
event/event_loop.h
|
||||
event/timer.h
|
||||
)
|
||||
@@ -306,6 +310,8 @@ SOURCE_GROUP(Net FILES
|
||||
net/packet.h
|
||||
net/servertalk_client_connection.cpp
|
||||
net/servertalk_client_connection.h
|
||||
net/servertalk_legacy_client_connection.cpp
|
||||
net/servertalk_legacy_client_connection.h
|
||||
net/servertalk_common.h
|
||||
net/servertalk_server.cpp
|
||||
net/servertalk_server.h
|
||||
|
||||
@@ -1534,8 +1534,6 @@ uint32 Database::GetGroupID(const char* name){
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
{
|
||||
// Commenting this out until logging levels can prevent this from going to console
|
||||
//Log.Out(Logs::General, Logs::None,, "Character not in a group: %s", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ void EQEmuConfig::do_world(TiXmlElement *ele)
|
||||
if (text) {
|
||||
LoginPort = atoi(text);
|
||||
}
|
||||
text = ParseTextBlock(sub_ele, "legacy", true);
|
||||
if (text) {
|
||||
LoginLegacy = atoi(text) > 0 ? true : false;
|
||||
}
|
||||
text = ParseTextBlock(sub_ele, "account", true);
|
||||
if (text) {
|
||||
LoginAccount = text;
|
||||
@@ -89,6 +93,10 @@ void EQEmuConfig::do_world(TiXmlElement *ele)
|
||||
if (text) {
|
||||
loginconfig->LoginPort = atoi(text);
|
||||
}
|
||||
text = ParseTextBlock(sub_ele, "legacy", true);
|
||||
if (text) {
|
||||
loginconfig->LoginLegacy = atoi(text) > 0 ? true : false;
|
||||
}
|
||||
text = ParseTextBlock(sub_ele, "account", true);
|
||||
if (text) {
|
||||
loginconfig->LoginAccount = text;
|
||||
@@ -370,6 +378,9 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const
|
||||
if (var_name == "LoginPort") {
|
||||
return (itoa(LoginPort));
|
||||
}
|
||||
if (var_name == "LoginLegacy") {
|
||||
return (itoa(LoginLegacy ? 1 : 0));
|
||||
}
|
||||
if (var_name == "Locked") {
|
||||
return (Locked ? "true" : "false");
|
||||
}
|
||||
@@ -495,6 +506,7 @@ void EQEmuConfig::Dump() const
|
||||
std::cout << "LoginAccount = " << LoginAccount << std::endl;
|
||||
std::cout << "LoginPassword = " << LoginPassword << std::endl;
|
||||
std::cout << "LoginPort = " << LoginPort << std::endl;
|
||||
std::cout << "LoginLegacy = " << LoginLegacy << std::endl;
|
||||
std::cout << "Locked = " << Locked << std::endl;
|
||||
std::cout << "WorldTCPPort = " << WorldTCPPort << std::endl;
|
||||
std::cout << "WorldIP = " << WorldIP << std::endl;
|
||||
|
||||
@@ -26,6 +26,7 @@ struct LoginConfig {
|
||||
std::string LoginAccount;
|
||||
std::string LoginPassword;
|
||||
uint16 LoginPort;
|
||||
bool LoginLegacy;
|
||||
};
|
||||
|
||||
class EQEmuConfig : public XMLParser
|
||||
@@ -42,6 +43,7 @@ class EQEmuConfig : public XMLParser
|
||||
std::string LoginAccount;
|
||||
std::string LoginPassword;
|
||||
uint16 LoginPort;
|
||||
bool LoginLegacy;
|
||||
uint32 LoginCount;
|
||||
LinkedList<LoginConfig*> loginlist;
|
||||
bool Locked;
|
||||
@@ -127,8 +129,9 @@ class EQEmuConfig : public XMLParser
|
||||
#include "eqemu_config_elements.h"
|
||||
// Set sane defaults
|
||||
// Login server
|
||||
LoginHost = "eqemulator.net";
|
||||
LoginHost = "login.eqemulator.net";
|
||||
LoginPort = 5998;
|
||||
LoginLegacy = true;
|
||||
// World
|
||||
Locked = false;
|
||||
WorldTCPPort = 9000;
|
||||
|
||||
@@ -19,7 +19,6 @@ EQ::Net::DaybreakConnectionManager::DaybreakConnectionManager(const DaybreakConn
|
||||
m_attached = nullptr;
|
||||
m_options = opts;
|
||||
memset(&m_timer, 0, sizeof(uv_timer_t));
|
||||
memset(&m_resend_timer, 0, sizeof(uv_timer_t));
|
||||
memset(&m_socket, 0, sizeof(uv_udp_t));
|
||||
|
||||
Attach(EQ::EventLoop::Get().Handle());
|
||||
@@ -34,19 +33,15 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
|
||||
{
|
||||
if (!m_attached) {
|
||||
uv_timer_init(loop, &m_timer);
|
||||
uv_timer_init(loop, &m_resend_timer);
|
||||
m_timer.data = this;
|
||||
m_resend_timer.data = this;
|
||||
|
||||
auto update_rate = (uint64_t)(1000.0 / m_options.tic_rate_hertz);
|
||||
|
||||
uv_timer_start(&m_timer, [](uv_timer_t *handle) {
|
||||
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
|
||||
c->Process();
|
||||
}, 2, 2);
|
||||
|
||||
uv_timer_start(&m_resend_timer, [](uv_timer_t *handle) {
|
||||
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
|
||||
c->ProcessResend();
|
||||
}, 5, 5);
|
||||
}, update_rate, update_rate);
|
||||
|
||||
uv_udp_init(loop, &m_socket);
|
||||
m_socket.data = this;
|
||||
@@ -187,12 +182,12 @@ void EQ::Net::DaybreakConnectionManager::ProcessPacket(const std::string &endpoi
|
||||
try {
|
||||
auto connection = FindConnectionByEndpoint(endpoint, port);
|
||||
if (connection) {
|
||||
ReadOnlyPacket p((void*)data, size);
|
||||
StaticPacket p((void*)data, size);
|
||||
connection->ProcessPacket(p);
|
||||
}
|
||||
else {
|
||||
if (data[0] == 0 && data[1] == OP_SessionRequest) {
|
||||
ReadOnlyPacket p((void*)data, size);
|
||||
StaticPacket p((void*)data, size);
|
||||
auto request = p.GetSerialize<DaybreakConnect>(0);
|
||||
|
||||
connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, request, endpoint, port));
|
||||
@@ -232,7 +227,7 @@ void EQ::Net::DaybreakConnectionManager::SendDisconnect(const std::string &addr,
|
||||
header.opcode = OP_SessionDisconnect;
|
||||
header.connect_code = 0;
|
||||
|
||||
WritablePacket out;
|
||||
DynamicPacket out;
|
||||
out.PutSerialize(0, header);
|
||||
|
||||
uv_udp_send_t *send_req = new uv_udp_send_t;
|
||||
@@ -270,6 +265,9 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner
|
||||
m_buffered_packets_length = 0;
|
||||
m_resend_delay = m_owner->m_options.resend_delay_ms;
|
||||
m_rolling_ping = 100;
|
||||
m_combined.reset(new char[512]);
|
||||
m_combined[0] = 0;
|
||||
m_combined[1] = OP_Combined;
|
||||
m_last_session_stats = Clock::now();
|
||||
}
|
||||
|
||||
@@ -304,7 +302,7 @@ void EQ::Net::DaybreakConnection::Close()
|
||||
disconnect.zero = 0;
|
||||
disconnect.opcode = OP_SessionDisconnect;
|
||||
disconnect.connect_code = HostToNetwork(m_connect_code);
|
||||
WritablePacket out;
|
||||
DynamicPacket out;
|
||||
out.PutSerialize(0, disconnect);
|
||||
InternalSend(out);
|
||||
|
||||
@@ -328,7 +326,7 @@ void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream)
|
||||
void EQ::Net::DaybreakConnection::QueuePacket(Packet &p, int stream, bool reliable)
|
||||
{
|
||||
if (*(char*)p.Data() == 0) {
|
||||
WritablePacket packet;
|
||||
DynamicPacket packet;
|
||||
packet.PutUInt8(0, 0);
|
||||
packet.PutPacket(1, p);
|
||||
InternalQueuePacket(packet, stream, reliable);
|
||||
@@ -395,7 +393,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
EQ::Net::WritablePacket temp;
|
||||
EQ::Net::DynamicPacket temp;
|
||||
temp.PutPacket(0, p);
|
||||
temp.Resize(temp.Length() - m_crc_bytes);
|
||||
|
||||
@@ -412,7 +410,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
}
|
||||
}
|
||||
|
||||
ProcessDecodedPacket(ReadOnlyPacket(temp.Data(), temp.Length()));
|
||||
ProcessDecodedPacket(StaticPacket(temp.Data(), temp.Length()));
|
||||
}
|
||||
else {
|
||||
ProcessDecodedPacket(p);
|
||||
@@ -454,7 +452,7 @@ void EQ::Net::DaybreakConnection::AddToQueue(int stream, uint16_t seq, const Pac
|
||||
auto s = &m_streams[stream];
|
||||
auto iter = s->packet_queue.find(seq);
|
||||
if (iter == s->packet_queue.end()) {
|
||||
WritablePacket *out = new WritablePacket();
|
||||
DynamicPacket *out = new DynamicPacket();
|
||||
out->PutPacket(0, p);
|
||||
|
||||
s->packet_queue.insert(std::make_pair(seq, out));
|
||||
@@ -480,7 +478,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessDecodedPacket(ReadOnlyPacket(current, subpacket_length));
|
||||
ProcessDecodedPacket(StaticPacket(current, subpacket_length));
|
||||
current += subpacket_length;
|
||||
}
|
||||
break;
|
||||
@@ -525,7 +523,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
current += 1;
|
||||
}
|
||||
|
||||
ProcessDecodedPacket(ReadOnlyPacket(current, subpacket_length));
|
||||
ProcessDecodedPacket(StaticPacket(current, subpacket_length));
|
||||
current += subpacket_length;
|
||||
}
|
||||
}
|
||||
@@ -548,7 +546,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
reply.max_packet_size = HostToNetwork(m_max_packet_size);
|
||||
reply.encode_pass1 = m_encode_passes[0];
|
||||
reply.encode_pass2 = m_encode_passes[1];
|
||||
WritablePacket p;
|
||||
DynamicPacket p;
|
||||
p.PutSerialize(0, reply);
|
||||
InternalSend(p);
|
||||
}
|
||||
@@ -578,7 +576,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
RemoveFromQueue(stream_id, sequence);
|
||||
SendAck(stream_id, stream->sequence_in);
|
||||
stream->sequence_in++;
|
||||
ReadOnlyPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
|
||||
StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size());
|
||||
ProcessDecodedPacket(next);
|
||||
}
|
||||
|
||||
@@ -670,7 +668,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
disconnect.zero = 0;
|
||||
disconnect.opcode = OP_SessionDisconnect;
|
||||
disconnect.connect_code = HostToNetwork(m_connect_code);
|
||||
WritablePacket out;
|
||||
DynamicPacket out;
|
||||
out.PutSerialize(0, disconnect);
|
||||
InternalSend(out);
|
||||
}
|
||||
@@ -683,7 +681,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
{
|
||||
auto self = m_self.lock();
|
||||
if (m_owner->m_on_packet_recv && self) {
|
||||
m_owner->m_on_packet_recv(self, ReadOnlyPacket((char*)p.Data() + 1, p.Length() - 1));
|
||||
m_owner->m_on_packet_recv(self, StaticPacket((char*)p.Data() + 1, p.Length() - 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -700,7 +698,7 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
response.client_recv = request.packets_recv;
|
||||
response.server_sent = EQ::Net::HostToNetwork(m_stats.sent_packets);
|
||||
response.server_recv = EQ::Net::HostToNetwork(m_stats.recv_packets);
|
||||
WritablePacket out;
|
||||
DynamicPacket out;
|
||||
out.PutSerialize(0, response);
|
||||
InternalSend(out);
|
||||
break;
|
||||
@@ -1023,7 +1021,7 @@ void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq)
|
||||
ack.opcode = OP_Ack + stream_id;
|
||||
ack.sequence = HostToNetwork(seq);
|
||||
|
||||
WritablePacket p;
|
||||
DynamicPacket p;
|
||||
p.PutSerialize(0, ack);
|
||||
|
||||
InternalBufferedSend(p);
|
||||
@@ -1036,7 +1034,7 @@ void EQ::Net::DaybreakConnection::SendOutOfOrderAck(int stream_id, uint16_t seq)
|
||||
ack.opcode = OP_OutOfOrderAck + stream_id;
|
||||
ack.sequence = HostToNetwork(seq);
|
||||
|
||||
WritablePacket p;
|
||||
DynamicPacket p;
|
||||
p.PutSerialize(0, ack);
|
||||
|
||||
InternalBufferedSend(p);
|
||||
@@ -1076,7 +1074,7 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p)
|
||||
FlushBuffer();
|
||||
}
|
||||
|
||||
WritablePacket copy;
|
||||
DynamicPacket copy;
|
||||
copy.PutPacket(0, p);
|
||||
m_buffered_packets.push_back(copy);
|
||||
m_buffered_packets_length += p.Length();
|
||||
@@ -1095,7 +1093,7 @@ void EQ::Net::DaybreakConnection::SendConnect()
|
||||
connect.connect_code = (uint32_t)HostToNetwork(m_connect_code);
|
||||
connect.max_packet_size = HostToNetwork((uint32_t)m_owner->m_options.max_packet_size);
|
||||
|
||||
WritablePacket p;
|
||||
DynamicPacket p;
|
||||
p.PutSerialize(0, connect);
|
||||
|
||||
InternalSend(p);
|
||||
@@ -1107,7 +1105,7 @@ void EQ::Net::DaybreakConnection::SendKeepAlive()
|
||||
keep_alive.zero = 0;
|
||||
keep_alive.opcode = OP_KeepAlive;
|
||||
|
||||
WritablePacket p;
|
||||
DynamicPacket p;
|
||||
p.PutSerialize(0, keep_alive);
|
||||
|
||||
InternalSend(p);
|
||||
@@ -1123,7 +1121,7 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
|
||||
};
|
||||
|
||||
if (PacketCanBeEncoded(p)) {
|
||||
WritablePacket out;
|
||||
DynamicPacket out;
|
||||
out.PutPacket(0, p);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
@@ -1210,7 +1208,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
||||
|
||||
size_t used = 0;
|
||||
size_t sublen = m_max_packet_size - m_crc_bytes - DaybreakReliableFragmentHeader::size();
|
||||
WritablePacket first_packet;
|
||||
DynamicPacket first_packet;
|
||||
first_packet.PutSerialize(0, first_header);
|
||||
first_packet.PutData(DaybreakReliableFragmentHeader::size(), (char*)p.Data() + used, sublen);
|
||||
used += sublen;
|
||||
@@ -1227,7 +1225,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
||||
|
||||
while (used < length) {
|
||||
auto left = length - used;
|
||||
WritablePacket packet;
|
||||
DynamicPacket packet;
|
||||
DaybreakReliableHeader header;
|
||||
header.zero = 0;
|
||||
header.opcode = OP_Fragment + stream_id;
|
||||
@@ -1255,7 +1253,7 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
|
||||
}
|
||||
}
|
||||
else {
|
||||
WritablePacket packet;
|
||||
DynamicPacket packet;
|
||||
DaybreakReliableHeader header;
|
||||
header.zero = 0;
|
||||
header.opcode = OP_Packet + stream_id;
|
||||
@@ -1282,22 +1280,15 @@ void EQ::Net::DaybreakConnection::FlushBuffer()
|
||||
}
|
||||
|
||||
if (m_buffered_packets.size() > 1) {
|
||||
WritablePacket out;
|
||||
DaybreakHeader header;
|
||||
header.zero = 0;
|
||||
header.opcode = OP_Combined;
|
||||
size_t offset = 0;
|
||||
|
||||
out.PutSerialize(offset, header);
|
||||
offset += DaybreakHeader::size();
|
||||
|
||||
StaticPacket out(m_combined.get(), 512);
|
||||
size_t length = 2;
|
||||
for (auto &p : m_buffered_packets) {
|
||||
out.PutUInt8(offset, (uint8_t)p.Length());
|
||||
offset += 1;
|
||||
out.PutPacket(offset, p);
|
||||
offset += p.Length();
|
||||
out.PutUInt8(length, (uint8_t)p.Length());
|
||||
out.PutPacket(length + 1, p);
|
||||
length += (1 + p.Length());
|
||||
}
|
||||
|
||||
out.Resize(length);
|
||||
InternalSend(out);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -140,8 +140,9 @@ namespace EQ
|
||||
Timestamp m_last_recv;
|
||||
DbProtocolStatus m_status;
|
||||
Timestamp m_hold_time;
|
||||
std::list<WritablePacket> m_buffered_packets;
|
||||
std::list<DynamicPacket> m_buffered_packets;
|
||||
size_t m_buffered_packets_length;
|
||||
std::unique_ptr<char[]> m_combined;
|
||||
Timestamp m_last_stats;
|
||||
DaybreakConnectionStats m_stats;
|
||||
Timestamp m_last_session_stats;
|
||||
@@ -150,7 +151,7 @@ namespace EQ
|
||||
|
||||
struct DaybreakSentPacket
|
||||
{
|
||||
WritablePacket packet;
|
||||
DynamicPacket packet;
|
||||
Timestamp last_sent;
|
||||
Timestamp first_sent;
|
||||
size_t times_resent;
|
||||
@@ -169,7 +170,7 @@ namespace EQ
|
||||
uint16_t sequence_out;
|
||||
std::map<uint16_t, Packet*> packet_queue;
|
||||
|
||||
WritablePacket fragment_packet;
|
||||
DynamicPacket fragment_packet;
|
||||
uint32_t fragment_current_bytes;
|
||||
uint32_t fragment_total_bytes;
|
||||
|
||||
@@ -216,12 +217,12 @@ namespace EQ
|
||||
{
|
||||
DaybreakConnectionManagerOptions() {
|
||||
max_connection_count = 0;
|
||||
keepalive_delay_ms = 0;
|
||||
resend_delay_ms = 10;
|
||||
resend_delay_factor = 1.25;
|
||||
stats_delay_ms = 0;
|
||||
keepalive_delay_ms = 9000;
|
||||
resend_delay_ms = 25;
|
||||
resend_delay_factor = 1.5;
|
||||
stats_delay_ms = 9000;
|
||||
connect_delay_ms = 1000;
|
||||
stale_connection_ms = 135000;
|
||||
stale_connection_ms = 30000;
|
||||
crc_length = 2;
|
||||
max_packet_size = 512;
|
||||
encode_passes[0] = DaybreakEncodeType::EncodeNone;
|
||||
@@ -231,6 +232,7 @@ namespace EQ
|
||||
hold_length_ms = 50;
|
||||
simulated_in_packet_loss = 0;
|
||||
simulated_out_packet_loss = 0;
|
||||
tic_rate_hertz = 20.0;
|
||||
}
|
||||
|
||||
size_t max_packet_size;
|
||||
@@ -246,6 +248,7 @@ namespace EQ
|
||||
size_t hold_length_ms;
|
||||
size_t simulated_in_packet_loss;
|
||||
size_t simulated_out_packet_loss;
|
||||
double tic_rate_hertz;
|
||||
DaybreakEncodeType encode_passes[2];
|
||||
int port;
|
||||
};
|
||||
@@ -269,7 +272,6 @@ namespace EQ
|
||||
|
||||
EQEmu::Random m_rand;
|
||||
uv_timer_t m_timer;
|
||||
uv_timer_t m_resend_timer;
|
||||
uv_udp_t m_socket;
|
||||
uv_loop_t *m_attached;
|
||||
DaybreakConnectionManagerOptions m_options;
|
||||
|
||||
@@ -42,7 +42,7 @@ void EQ::Net::EQStreamManager::DaybreakPacketRecv(std::shared_ptr<DaybreakConnec
|
||||
auto iter = m_streams.find(connection);
|
||||
if (iter != m_streams.end()) {
|
||||
auto &stream = iter->second;
|
||||
std::unique_ptr<EQ::Net::Packet> t(new EQ::Net::WritablePacket());
|
||||
std::unique_ptr<EQ::Net::Packet> t(new EQ::Net::DynamicPacket());
|
||||
t->PutPacket(0, p);
|
||||
stream->m_packet_queue.push_back(std::move(t));
|
||||
|
||||
@@ -73,7 +73,7 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req)
|
||||
opcode = (*m_opcode_manager)->EmuToEQ(p->GetOpcode());
|
||||
}
|
||||
|
||||
EQ::Net::WritablePacket out;
|
||||
EQ::Net::DynamicPacket out;
|
||||
switch (m_owner->m_options.opcode_size) {
|
||||
case 1:
|
||||
out.PutUInt8(0, opcode);
|
||||
|
||||
@@ -334,3 +334,12 @@ std::string EQ::Net::Packet::ToString(size_t line_length) const
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EQ::Net::StaticPacket::Resize(size_t new_size)
|
||||
{
|
||||
if (new_size > m_max_data_length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_data_length = new_size;
|
||||
}
|
||||
|
||||
+20
-17
@@ -13,7 +13,7 @@ namespace EQ {
|
||||
class Packet
|
||||
{
|
||||
public:
|
||||
Packet() { }
|
||||
Packet() : m_stream(std::ios::out | std::ios::binary) { }
|
||||
virtual ~Packet() { }
|
||||
|
||||
virtual const void *Data() const = 0;
|
||||
@@ -36,11 +36,11 @@ namespace EQ {
|
||||
|
||||
template<typename T>
|
||||
void PutSerialize(size_t offset, const T &value) {
|
||||
std::stringstream buffer(std::ios::in | std::ios::out | std::ios::binary);
|
||||
cereal::BinaryOutputArchive output(buffer);
|
||||
m_stream.clear();
|
||||
cereal::BinaryOutputArchive output(m_stream);
|
||||
output(value);
|
||||
|
||||
auto str = buffer.str();
|
||||
auto &str = m_stream.str();
|
||||
if (Length() < offset + str.length()) {
|
||||
if (!Resize(offset + str.length())) {
|
||||
throw std::out_of_range("Packet::PutSerialize(), could not resize packet and would of written past the end.");
|
||||
@@ -80,38 +80,41 @@ namespace EQ {
|
||||
|
||||
std::string ToString() const;
|
||||
std::string ToString(size_t line_length) const;
|
||||
protected:
|
||||
std::stringstream m_stream;
|
||||
};
|
||||
|
||||
class ReadOnlyPacket : public Packet
|
||||
class StaticPacket : public Packet
|
||||
{
|
||||
public:
|
||||
ReadOnlyPacket(void *data, size_t size) { m_data = data; m_data_length = size; }
|
||||
virtual ~ReadOnlyPacket() { }
|
||||
ReadOnlyPacket(const ReadOnlyPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; }
|
||||
ReadOnlyPacket& operator=(const ReadOnlyPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; return *this; }
|
||||
ReadOnlyPacket(ReadOnlyPacket &&o) { m_data = o.m_data; m_data_length = o.m_data_length; }
|
||||
StaticPacket(void *data, size_t size) { m_data = data; m_data_length = size; m_max_data_length = size; }
|
||||
virtual ~StaticPacket() { }
|
||||
StaticPacket(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; }
|
||||
StaticPacket& operator=(const StaticPacket &o) { m_data = o.m_data; m_data_length = o.m_data_length; return *this; }
|
||||
StaticPacket(StaticPacket &&o) { m_data = o.m_data; m_data_length = o.m_data_length; }
|
||||
|
||||
virtual const void *Data() const { return m_data; }
|
||||
virtual void *Data() { return m_data; }
|
||||
virtual size_t Length() const { return m_data_length; }
|
||||
virtual size_t Length() { return m_data_length; }
|
||||
virtual bool Clear() { return false; }
|
||||
virtual bool Resize(size_t new_size) { return false; }
|
||||
virtual bool Resize(size_t new_size);
|
||||
virtual void Reserve(size_t new_size) { }
|
||||
|
||||
protected:
|
||||
void *m_data;
|
||||
size_t m_data_length;
|
||||
size_t m_max_data_length;
|
||||
};
|
||||
|
||||
class WritablePacket : public Packet
|
||||
class DynamicPacket : public Packet
|
||||
{
|
||||
public:
|
||||
WritablePacket() { }
|
||||
virtual ~WritablePacket() { }
|
||||
WritablePacket(WritablePacket &&o) { m_data = std::move(o.m_data); }
|
||||
WritablePacket(const WritablePacket &o) { m_data = o.m_data; }
|
||||
WritablePacket& operator=(const WritablePacket &o) { m_data = o.m_data; return *this; }
|
||||
DynamicPacket() { }
|
||||
virtual ~DynamicPacket() { }
|
||||
DynamicPacket(DynamicPacket &&o) { m_data = std::move(o.m_data); }
|
||||
DynamicPacket(const DynamicPacket &o) { m_data = o.m_data; }
|
||||
DynamicPacket& operator=(const DynamicPacket &o) { m_data = o.m_data; return *this; }
|
||||
|
||||
virtual const void *Data() const { return &m_data[0]; }
|
||||
virtual void *Data() { return &m_data[0]; }
|
||||
|
||||
@@ -21,7 +21,7 @@ EQ::Net::ServertalkClient::~ServertalkClient()
|
||||
|
||||
void EQ::Net::ServertalkClient::Send(uint16_t opcode, EQ::Net::Packet &p)
|
||||
{
|
||||
EQ::Net::WritablePacket out;
|
||||
EQ::Net::DynamicPacket out;
|
||||
#ifdef ENABLE_SECURITY
|
||||
if (m_encrypted) {
|
||||
if (p.Length() == 0) {
|
||||
@@ -52,7 +52,7 @@ void EQ::Net::ServertalkClient::Send(uint16_t opcode, EQ::Net::Packet &p)
|
||||
|
||||
void EQ::Net::ServertalkClient::SendPacket(ServerPacket *p)
|
||||
{
|
||||
EQ::Net::ReadOnlyPacket pout(p->pBuffer, p->size);
|
||||
EQ::Net::StaticPacket pout(p->pBuffer, p->size);
|
||||
Send(p->opcode, pout);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ void EQ::Net::ServertalkClient::ProcessData(EQ::Net::TCPConnection *c, const uns
|
||||
|
||||
void EQ::Net::ServertalkClient::SendHello()
|
||||
{
|
||||
EQ::Net::WritablePacket p;
|
||||
EQ::Net::DynamicPacket p;
|
||||
InternalSend(ServertalkClientHello, p);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ void EQ::Net::ServertalkClient::InternalSend(ServertalkPacketType type, EQ::Net:
|
||||
if (!m_connection)
|
||||
return;
|
||||
|
||||
EQ::Net::WritablePacket out;
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt32(0, (uint32_t)p.Length());
|
||||
out.PutUInt8(4, (uint8_t)type);
|
||||
if (p.Length() > 0) {
|
||||
@@ -145,7 +145,7 @@ void EQ::Net::ServertalkClient::ProcessReadBuffer()
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
EQ::Net::WritablePacket p;
|
||||
EQ::Net::DynamicPacket p;
|
||||
switch (type) {
|
||||
case ServertalkServerHello:
|
||||
ProcessHello(p);
|
||||
@@ -156,7 +156,7 @@ void EQ::Net::ServertalkClient::ProcessReadBuffer()
|
||||
}
|
||||
}
|
||||
else {
|
||||
EQ::Net::ReadOnlyPacket p(&m_buffer[current + 5], length);
|
||||
EQ::Net::StaticPacket p(&m_buffer[current + 5], length);
|
||||
switch (type) {
|
||||
case ServertalkServerHello:
|
||||
ProcessHello(p);
|
||||
@@ -272,7 +272,7 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
EQ::Net::ReadOnlyPacket decrypted_packet(&decrypted_text[0], message_len);
|
||||
EQ::Net::StaticPacket decrypted_packet(&decrypted_text[0], message_len);
|
||||
|
||||
(*(uint64_t*)&m_nonce_theirs[0])++;
|
||||
|
||||
@@ -283,7 +283,7 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
||||
}
|
||||
else {
|
||||
size_t message_len = length;
|
||||
EQ::Net::ReadOnlyPacket packet(&data[0], message_len);
|
||||
EQ::Net::StaticPacket packet(&data[0], message_len);
|
||||
|
||||
auto cb = m_message_callbacks.find(opcode);
|
||||
if (cb != m_message_callbacks.end()) {
|
||||
@@ -309,7 +309,7 @@ void EQ::Net::ServertalkClient::ProcessMessage(EQ::Net::Packet &p)
|
||||
|
||||
void EQ::Net::ServertalkClient::SendHandshake(bool downgrade)
|
||||
{
|
||||
EQ::Net::WritablePacket handshake;
|
||||
EQ::Net::DynamicPacket handshake;
|
||||
#ifdef ENABLE_SECURITY
|
||||
if (m_encrypted) {
|
||||
crypto_box_keypair(m_public_key_ours, m_private_key_ours);
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "servertalk_legacy_client_connection.h"
|
||||
#include "dns.h"
|
||||
#include "../eqemu_logsys.h"
|
||||
|
||||
EQ::Net::ServertalkLegacyClient::ServertalkLegacyClient(const std::string &addr, int port, bool ipv6)
|
||||
: m_timer(std::unique_ptr<EQ::Timer>(new EQ::Timer(100, true, std::bind(&EQ::Net::ServertalkLegacyClient::Connect, this))))
|
||||
{
|
||||
m_port = port;
|
||||
m_ipv6 = ipv6;
|
||||
m_connecting = false;
|
||||
DNSLookup(addr, port, false, [this](const std::string &address) {
|
||||
m_addr = address;
|
||||
});
|
||||
}
|
||||
|
||||
EQ::Net::ServertalkLegacyClient::~ServertalkLegacyClient()
|
||||
{
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::Send(uint16_t opcode, EQ::Net::Packet &p)
|
||||
{
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt16(0, opcode);
|
||||
out.PutUInt16(2, p.Length());
|
||||
out.PutPacket(4, p);
|
||||
|
||||
InternalSend(ServertalkMessage, out);
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::SendPacket(ServerPacket *p)
|
||||
{
|
||||
EQ::Net::StaticPacket pout(p->pBuffer, p->size);
|
||||
Send(p->opcode, pout);
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb)
|
||||
{
|
||||
m_message_callbacks.insert(std::make_pair(opcode, cb));
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::Connect()
|
||||
{
|
||||
if (m_addr.length() == 0 || m_port == 0 || m_connection || m_connecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_connecting = true;
|
||||
EQ::Net::TCPConnection::Connect(m_addr, m_port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
if (connection == nullptr) {
|
||||
Log.OutF(Logs::General, Logs::TCP_Connection, "Error connecting to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
m_connecting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Log.OutF(Logs::General, Logs::TCP_Connection, "Connected to {0}:{1}", m_addr, m_port);
|
||||
m_connection = connection;
|
||||
m_connection->OnDisconnect([this](EQ::Net::TCPConnection *c) {
|
||||
Log.OutF(Logs::General, Logs::TCP_Connection, "Connection lost to {0}:{1}, attempting to reconnect...", m_addr, m_port);
|
||||
m_connection.reset();
|
||||
});
|
||||
|
||||
m_connection->OnRead(std::bind(&EQ::Net::ServertalkLegacyClient::ProcessData, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_connection->Start();
|
||||
m_connecting = false;
|
||||
|
||||
if (m_on_connect_cb) {
|
||||
m_on_connect_cb(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length)
|
||||
{
|
||||
m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + length);
|
||||
ProcessReadBuffer();
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::InternalSend(ServertalkPacketType type, EQ::Net::Packet &p)
|
||||
{
|
||||
if (!m_connection)
|
||||
return;
|
||||
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt32(0, (uint32_t)p.Length());
|
||||
out.PutUInt8(4, (uint8_t)type);
|
||||
if (p.Length() > 0) {
|
||||
out.PutPacket(5, p);
|
||||
}
|
||||
|
||||
m_connection->Write((const char*)out.Data(), out.Length());
|
||||
}
|
||||
|
||||
void EQ::Net::ServertalkLegacyClient::ProcessReadBuffer()
|
||||
{
|
||||
size_t current = 0;
|
||||
size_t total = m_buffer.size();
|
||||
|
||||
while (current < total) {
|
||||
auto left = total - current;
|
||||
|
||||
/*
|
||||
//header:
|
||||
//uint16 opcode;
|
||||
//uint16 length;
|
||||
*/
|
||||
uint16_t length = 0;
|
||||
uint16_t opcode = 0;
|
||||
if (left < 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
opcode = *(uint16_t*)&m_buffer[current];
|
||||
length = *(uint16_t*)&m_buffer[current + 2] - 4;
|
||||
|
||||
if (current + 4 + length > total) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
EQ::Net::DynamicPacket p;
|
||||
|
||||
auto cb = m_message_callbacks.find(opcode);
|
||||
if (cb != m_message_callbacks.end()) {
|
||||
cb->second(opcode, p);
|
||||
}
|
||||
}
|
||||
else {
|
||||
EQ::Net::StaticPacket p(&m_buffer[current + 4], length);
|
||||
|
||||
auto cb = m_message_callbacks.find(opcode);
|
||||
if (cb != m_message_callbacks.end()) {
|
||||
cb->second(opcode, p);
|
||||
}
|
||||
}
|
||||
|
||||
current += length + 4;
|
||||
}
|
||||
|
||||
if (current == total) {
|
||||
m_buffer.clear();
|
||||
}
|
||||
else {
|
||||
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + current);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_connection.h"
|
||||
#include "../event/timer.h"
|
||||
#include "servertalk_common.h"
|
||||
#include "packet.h"
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
class ServertalkLegacyClient
|
||||
{
|
||||
public:
|
||||
ServertalkLegacyClient(const std::string &addr, int port, bool ipv6);
|
||||
~ServertalkLegacyClient();
|
||||
|
||||
void Send(uint16_t opcode, EQ::Net::Packet &p);
|
||||
void SendPacket(ServerPacket *p);
|
||||
void OnConnect(std::function<void(ServertalkLegacyClient*)> cb) { m_on_connect_cb = cb; }
|
||||
void OnMessage(uint16_t opcode, std::function<void(uint16_t, EQ::Net::Packet&)> cb);
|
||||
bool Connected() const { return m_connecting != true; }
|
||||
|
||||
std::shared_ptr<EQ::Net::TCPConnection> Handle() { return m_connection; }
|
||||
private:
|
||||
void Connect();
|
||||
void ProcessData(EQ::Net::TCPConnection *c, const unsigned char *data, size_t length);
|
||||
void InternalSend(ServertalkPacketType type, EQ::Net::Packet &p);
|
||||
void ProcessReadBuffer();
|
||||
|
||||
std::unique_ptr<EQ::Timer> m_timer;
|
||||
|
||||
std::string m_addr;
|
||||
bool m_connecting;
|
||||
int m_port;
|
||||
bool m_ipv6;
|
||||
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
|
||||
std::vector<char> m_buffer;
|
||||
std::unordered_map<uint16_t, std::function<void(uint16_t, EQ::Net::Packet&)>> m_message_callbacks;
|
||||
std::function<void(ServertalkLegacyClient*)> m_on_connect_cb;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ EQ::Net::ServertalkServerConnection::~ServertalkServerConnection()
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet & p)
|
||||
{
|
||||
EQ::Net::WritablePacket out;
|
||||
EQ::Net::DynamicPacket out;
|
||||
#ifdef ENABLE_SECURITY
|
||||
if (m_encrypted) {
|
||||
if (p.Length() == 0) {
|
||||
@@ -50,7 +50,7 @@ void EQ::Net::ServertalkServerConnection::Send(uint16_t opcode, EQ::Net::Packet
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::SendPacket(ServerPacket * p)
|
||||
{
|
||||
EQ::Net::ReadOnlyPacket pout(p->pBuffer, p->size);
|
||||
EQ::Net::StaticPacket pout(p->pBuffer, p->size);
|
||||
Send(p->opcode, pout);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
EQ::Net::WritablePacket p;
|
||||
EQ::Net::DynamicPacket p;
|
||||
switch (type) {
|
||||
case ServertalkClientHello:
|
||||
{
|
||||
@@ -108,7 +108,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
|
||||
}
|
||||
}
|
||||
else {
|
||||
EQ::Net::ReadOnlyPacket p(&m_buffer[current + 5], length);
|
||||
EQ::Net::StaticPacket p(&m_buffer[current + 5], length);
|
||||
switch (type) {
|
||||
case ServertalkClientHello:
|
||||
{
|
||||
@@ -145,7 +145,7 @@ void EQ::Net::ServertalkServerConnection::OnDisconnect(TCPConnection *c)
|
||||
|
||||
void EQ::Net::ServertalkServerConnection::SendHello()
|
||||
{
|
||||
EQ::Net::WritablePacket hello;
|
||||
EQ::Net::DynamicPacket hello;
|
||||
|
||||
#ifdef ENABLE_SECURITY
|
||||
memset(m_public_key_ours, 0, crypto_box_PUBLICKEYBYTES);
|
||||
@@ -178,7 +178,7 @@ void EQ::Net::ServertalkServerConnection::InternalSend(ServertalkPacketType type
|
||||
if (!m_connection)
|
||||
return;
|
||||
|
||||
EQ::Net::WritablePacket out;
|
||||
EQ::Net::DynamicPacket out;
|
||||
out.PutUInt32(0, (uint32_t)p.Length());
|
||||
out.PutUInt8(4, (uint8_t)type);
|
||||
if (p.Length() > 0) {
|
||||
@@ -290,7 +290,7 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
EQ::Net::ReadOnlyPacket decrypted_packet(&decrypted_text[0], message_len);
|
||||
EQ::Net::StaticPacket decrypted_packet(&decrypted_text[0], message_len);
|
||||
|
||||
(*(uint64_t*)&m_nonce_theirs[0])++;
|
||||
|
||||
@@ -301,7 +301,7 @@ void EQ::Net::ServertalkServerConnection::ProcessMessage(EQ::Net::Packet &p)
|
||||
}
|
||||
else {
|
||||
size_t message_len = length;
|
||||
EQ::Net::ReadOnlyPacket packet(&data[0], message_len);
|
||||
EQ::Net::StaticPacket packet(&data[0], message_len);
|
||||
|
||||
auto cb = m_message_callbacks.find(opcode);
|
||||
if (cb != m_message_callbacks.end()) {
|
||||
|
||||
Reference in New Issue
Block a user