mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Some work on compression, the way the client does it is... bizarre and not how i orig thought it would be.
This commit is contained in:
@@ -41,12 +41,12 @@ void EQ::Net::DaybreakConnectionManager::Attach(uv_loop_t *loop)
|
||||
uv_timer_start(&m_timer, [](uv_timer_t *handle) {
|
||||
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
|
||||
c->Process();
|
||||
}, 5, 5);
|
||||
}, 2, 2);
|
||||
|
||||
uv_timer_start(&m_resend_timer, [](uv_timer_t *handle) {
|
||||
DaybreakConnectionManager *c = (DaybreakConnectionManager*)handle->data;
|
||||
c->ProcessResend();
|
||||
}, 50, 50);
|
||||
}, 10, 10);
|
||||
|
||||
uv_udp_init(loop, &m_socket);
|
||||
m_socket.data = this;
|
||||
@@ -88,6 +88,16 @@ void EQ::Net::DaybreakConnectionManager::Detach()
|
||||
|
||||
void EQ::Net::DaybreakConnectionManager::Connect(const std::string &addr, int port)
|
||||
{
|
||||
//todo dns resolution
|
||||
|
||||
auto connection = std::shared_ptr<DaybreakConnection>(new DaybreakConnection(this, addr, port));
|
||||
connection->m_self = connection;
|
||||
|
||||
if (m_on_new_connection) {
|
||||
m_on_new_connection(connection);
|
||||
}
|
||||
|
||||
m_connections.insert(std::make_pair(std::make_pair(addr, port), connection));
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnectionManager::Process()
|
||||
@@ -252,6 +262,7 @@ 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_last_session_stats = Clock::now();
|
||||
}
|
||||
|
||||
//new connection made as client
|
||||
@@ -271,6 +282,7 @@ 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_last_session_stats = Clock::now();
|
||||
}
|
||||
|
||||
EQ::Net::DaybreakConnection::~DaybreakConnection()
|
||||
@@ -284,7 +296,6 @@ void EQ::Net::DaybreakConnection::Close()
|
||||
disconnect.zero = 0;
|
||||
disconnect.opcode = OP_SessionDisconnect;
|
||||
disconnect.connect_code = HostToNetwork(m_connect_code);
|
||||
disconnect.disconnect_code = 6;
|
||||
WritablePacket out;
|
||||
out.PutSerialize(0, disconnect);
|
||||
InternalSend(out);
|
||||
@@ -344,7 +355,7 @@ void EQ::Net::DaybreakConnection::Process()
|
||||
ProcessQueue();
|
||||
|
||||
auto time_since_stats = (size_t)std::chrono::duration_cast<std::chrono::milliseconds>(now - m_last_stats).count();
|
||||
if (time_since_stats >= m_owner->m_options.stats_delay_ms) {
|
||||
if (m_owner->m_options.stats_delay_ms > 0 && time_since_stats >= m_owner->m_options.stats_delay_ms) {
|
||||
SendStatSync();
|
||||
m_last_stats = now;
|
||||
}
|
||||
@@ -376,40 +387,24 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_encode_passes[0] == EncodeCompression || m_encode_passes[1] == EncodeCompression) {
|
||||
EQ::Net::WritablePacket temp;
|
||||
temp.PutPacket(0, p);
|
||||
EQ::Net::WritablePacket temp;
|
||||
temp.PutPacket(0, p);
|
||||
temp.Resize(temp.Length() - m_crc_bytes);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
switch (m_encode_passes[i]) {
|
||||
case EncodeCompression:
|
||||
Log.OutF(Logs::General, Logs::Debug, "Decompressing packet on pass {1}\n{0}", temp.ToString(), i);
|
||||
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size() - m_crc_bytes);
|
||||
Log.OutF(Logs::General, Logs::Debug, "Decompressed packet on pass {1}\n{0}", temp.ToString(), i);
|
||||
break;
|
||||
case EncodeXOR:
|
||||
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size() - m_crc_bytes);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (int i = 1; i >= 0; --i) {
|
||||
switch (m_encode_passes[i]) {
|
||||
case EncodeCompression:
|
||||
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
||||
break;
|
||||
case EncodeXOR:
|
||||
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ProcessDecodedPacket(ReadOnlyPacket(temp.Data(), temp.Length() - m_crc_bytes));
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
switch (m_encode_passes[i]) {
|
||||
case EncodeXOR:
|
||||
Decode(p, DaybreakHeader::size(), p.Length() - DaybreakHeader::size() - m_crc_bytes);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessDecodedPacket(ReadOnlyPacket(p.Data(), p.Length() - m_crc_bytes));
|
||||
}
|
||||
ProcessDecodedPacket(ReadOnlyPacket(temp.Data(), temp.Length()));
|
||||
}
|
||||
else {
|
||||
ProcessDecodedPacket(p);
|
||||
@@ -667,7 +662,6 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
disconnect.zero = 0;
|
||||
disconnect.opcode = OP_SessionDisconnect;
|
||||
disconnect.connect_code = HostToNetwork(m_connect_code);
|
||||
disconnect.disconnect_code = 6;
|
||||
WritablePacket out;
|
||||
out.PutSerialize(0, disconnect);
|
||||
InternalSend(out);
|
||||
@@ -685,6 +679,24 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_SessionStatRequest:
|
||||
{
|
||||
auto request = p.GetSerialize<DaybreakSessionStatRequest>(0);
|
||||
|
||||
DaybreakSessionStatResponse response;
|
||||
response.zero = 0;
|
||||
response.opcode = OP_SessionStatResponse;
|
||||
response.timestamp = request.timestamp;
|
||||
response.our_timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
|
||||
response.client_sent = request.packets_sent;
|
||||
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;
|
||||
out.PutSerialize(0, response);
|
||||
InternalSend(out);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log.OutF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1));
|
||||
break;
|
||||
@@ -916,11 +928,13 @@ void EQ::Net::DaybreakConnection::Compress(Packet &p, size_t offset, size_t leng
|
||||
uint32_t new_length = 0;
|
||||
|
||||
if (length > 30) {
|
||||
new_length = Deflate(buffer, (uint32_t)length, new_buffer + 1, 2048);
|
||||
new_length = Deflate(buffer, (uint32_t)length, new_buffer + 1, 2048) + 1;
|
||||
new_buffer[0] = 0x5a;
|
||||
}
|
||||
else {
|
||||
memcpy(new_buffer + 1, buffer, length);
|
||||
new_buffer[0] = 0xa5;
|
||||
new_length = length + 1;
|
||||
}
|
||||
|
||||
p.Resize(offset);
|
||||
@@ -1013,7 +1027,21 @@ void EQ::Net::DaybreakConnection::SendOutOfOrderAck(int stream_id, uint16_t seq)
|
||||
|
||||
void EQ::Net::DaybreakConnection::SendStatSync()
|
||||
{
|
||||
//todo
|
||||
DaybreakSessionStatRequest request;
|
||||
request.zero = 0;
|
||||
request.opcode = OP_SessionStatRequest;
|
||||
request.timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() & 0xFFFFLL);
|
||||
request.stat_ping = m_stats.last_stat_ping;
|
||||
if (m_stats.total_stat_count > 0)
|
||||
request.avg_ping = m_stats.total_stat_ping / m_stats.total_stat_count;
|
||||
else
|
||||
request.avg_ping = 0;
|
||||
request.min_ping = m_stats.min_stat_ping;
|
||||
request.max_ping = m_stats.max_stat_ping;
|
||||
request.last_ping = m_stats.last_stat_ping;
|
||||
request.packets_sent = m_stats.sent_packets + 1;
|
||||
request.packets_recv = m_stats.recv_packets;
|
||||
m_last_session_stats = Clock::now();
|
||||
}
|
||||
|
||||
void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p)
|
||||
|
||||
@@ -82,6 +82,11 @@ namespace EQ
|
||||
total_acks = 0;
|
||||
min_ping = 0xFFFFFFFFFFFFFFFFUL;
|
||||
max_ping = 0;
|
||||
total_stat_ping = 0;
|
||||
total_stat_count = 0;
|
||||
min_stat_ping = 0xFFFFFFFFFFFFFFFFUL;
|
||||
max_stat_ping = 0;
|
||||
last_stat_ping = 0;
|
||||
created = Clock::now();
|
||||
}
|
||||
|
||||
@@ -93,6 +98,11 @@ namespace EQ
|
||||
uint64_t total_acks;
|
||||
uint64_t min_ping;
|
||||
uint64_t max_ping;
|
||||
uint64_t total_stat_ping;
|
||||
uint64_t total_stat_count;
|
||||
uint64_t min_stat_ping;
|
||||
uint64_t max_stat_ping;
|
||||
uint64_t last_stat_ping;
|
||||
Timestamp created;
|
||||
};
|
||||
|
||||
@@ -135,7 +145,6 @@ namespace EQ
|
||||
Timestamp m_last_stats;
|
||||
DaybreakConnectionStats m_stats;
|
||||
Timestamp m_last_session_stats;
|
||||
uint64_t m_last_session_stats_ping;
|
||||
size_t m_resend_delay;
|
||||
size_t m_rolling_ping;
|
||||
|
||||
@@ -209,7 +218,7 @@ namespace EQ
|
||||
max_connection_count = 0;
|
||||
keepalive_delay_ms = 0;
|
||||
resend_delay_ms = 1000;
|
||||
stats_delay_ms = 10000;
|
||||
stats_delay_ms = 0;
|
||||
connect_delay_ms = 1000;
|
||||
stale_connection_ms = 60000;
|
||||
crc_length = 2;
|
||||
|
||||
@@ -74,15 +74,13 @@ namespace EQ
|
||||
uint8_t zero;
|
||||
uint8_t opcode;
|
||||
uint32_t connect_code;
|
||||
uint16_t disconnect_code;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive(CEREAL_NVP(zero),
|
||||
CEREAL_NVP(opcode),
|
||||
CEREAL_NVP(connect_code),
|
||||
CEREAL_NVP(disconnect_code));
|
||||
CEREAL_NVP(connect_code));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -116,7 +114,7 @@ namespace EQ
|
||||
}
|
||||
};
|
||||
|
||||
struct DaybreakSessionStatRequestHeader
|
||||
struct DaybreakSessionStatRequest
|
||||
{
|
||||
static size_t size() { return 40; }
|
||||
uint8_t zero;
|
||||
@@ -146,7 +144,7 @@ namespace EQ
|
||||
}
|
||||
};
|
||||
|
||||
struct DaybreakSessionStatResponseHeader
|
||||
struct DaybreakSessionStatResponse
|
||||
{
|
||||
static size_t size() { return 40; }
|
||||
uint8_t zero;
|
||||
|
||||
+11
-10
@@ -17,20 +17,21 @@ namespace EQ
|
||||
opcode_size = 2;
|
||||
}
|
||||
|
||||
EQStreamManagerOptions(bool encoded, bool compressed) {
|
||||
EQStreamManagerOptions(int port, bool encoded, bool compressed) {
|
||||
opcode_size = 2;
|
||||
if (encoded) {
|
||||
daybreak_options.encode_passes[0] = EncodeXOR;
|
||||
|
||||
if (compressed) {
|
||||
daybreak_options.encode_passes[1] = EncodeCompression;
|
||||
}
|
||||
//World seems to support both compression and xor zone supports one or the others.
|
||||
//Enforce one or the other in the convienence construct
|
||||
//Login I had trouble getting to recognize compression at all
|
||||
//but that might be because it was still a bit buggy when i was testing that.
|
||||
if (compressed) {
|
||||
daybreak_options.encode_passes[0] = EncodeCompression;
|
||||
}
|
||||
else {
|
||||
if (compressed) {
|
||||
daybreak_options.encode_passes[0] = EncodeCompression;
|
||||
}
|
||||
else if (encoded) {
|
||||
daybreak_options.encode_passes[0] = EncodeXOR;
|
||||
}
|
||||
|
||||
daybreak_options.port = port;
|
||||
}
|
||||
|
||||
int opcode_size;
|
||||
|
||||
Reference in New Issue
Block a user