Bring back netcode to robust commit 34549a4 - proven and tested by PEQ and EZ as solid/stable with all of recent packet fixes

This commit is contained in:
Akkadius 2017-07-12 21:49:30 -05:00
parent 855796448c
commit 45b29aedf3
2 changed files with 60 additions and 122 deletions

View File

@ -141,7 +141,7 @@ void EQ::Net::DaybreakConnectionManager::Process()
connection->SendConnect();
}
}
break;
break;
case StatusConnected: {
if (m_options.keepalive_delay_ms != 0) {
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - connection->m_last_send);
@ -151,10 +151,10 @@ void EQ::Net::DaybreakConnectionManager::Process()
}
}
case StatusDisconnecting:
connection->Process();
break;
connection->Process();
break;
default:
break;
break;
}
iter++;
@ -172,10 +172,10 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend()
{
case StatusConnected:
case StatusDisconnecting:
connection->ProcessResend();
break;
connection->ProcessResend();
break;
default:
break;
break;
}
iter++;
@ -365,7 +365,7 @@ void EQ::Net::DaybreakConnection::Process()
FlushBuffer();
}
ProcessInboundQueue();
ProcessQueue();
}
catch (std::exception ex) {
LogF(Logs::Detail, Logs::Netcode, "Error processing connection: {0}", ex.what());
@ -407,13 +407,13 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
for (int i = 1; i >= 0; --i) {
switch (m_encode_passes[i]) {
case EncodeCompression:
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
break;
Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
break;
case EncodeXOR:
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
break;
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
break;
default:
break;
break;
}
}
@ -425,10 +425,10 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
for (int i = 1; i >= 0; --i) {
switch (m_encode_passes[i]) {
case EncodeXOR:
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
break;
Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size());
break;
default:
break;
break;
}
}
@ -440,7 +440,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p)
}
}
void EQ::Net::DaybreakConnection::ProcessInboundQueue()
void EQ::Net::DaybreakConnection::ProcessQueue()
{
for (int i = 0; i < 4; ++i) {
auto stream = &m_streams[i];
@ -459,31 +459,6 @@ void EQ::Net::DaybreakConnection::ProcessInboundQueue()
}
}
void EQ::Net::DaybreakConnection::ProcessOutboundQueue()
{
for (int i = 0; i < 4; ++i) {
auto stream = &m_streams[i];
if (stream->outstanding_bytes == 0) {
continue;
}
while (!stream->buffered_packets.empty()) {
auto &buff = stream->buffered_packets.front();
if (stream->outstanding_bytes + buff.sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes ||
stream->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) {
break;
}
stream->outstanding_bytes += buff.sent.packet.Length();
stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent));
InternalBufferedSend(buff.sent.packet);
stream->buffered_packets.pop_front();
}
}
}
void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq)
{
auto s = &m_streams[stream];
@ -779,10 +754,10 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p)
break;
}
case OP_SessionStatResponse:
break;
break;
default:
LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1));
break;
LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1));
break;
}
}
else {
@ -808,15 +783,15 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p)
int actual = 0;
switch (m_crc_bytes) {
case 2:
actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff;
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff;
break;
actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff;
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff;
break;
case 4:
actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]);
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key);
break;
actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]);
calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key);
break;
default:
return false;
return false;
}
if (actual == calculated) {
@ -835,13 +810,13 @@ void EQ::Net::DaybreakConnection::AppendCRC(Packet &p)
int calculated = 0;
switch (m_crc_bytes) {
case 2:
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff;
p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated));
break;
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff;
p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated));
break;
case 4:
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key);
p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated));
break;
calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key);
p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated));
break;
}
}
@ -1044,7 +1019,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream)
auto now = Clock::now();
auto s = &m_streams[stream];
for (auto &entry : s->outstanding_packets) {
for (auto &entry : s->sent_packets) {
auto time_since_last_send = std::chrono::duration_cast<std::chrono::milliseconds>(now - entry.second.last_sent);
if (entry.second.times_resent == 0) {
if ((size_t)time_since_last_send.count() > m_resend_delay) {
@ -1076,8 +1051,8 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
auto now = Clock::now();
auto s = &m_streams[stream];
auto iter = s->outstanding_packets.begin();
while (iter != s->outstanding_packets.end()) {
auto iter = s->sent_packets.begin();
while (iter != s->sent_packets.end()) {
auto order = CompareSequence(seq, iter->first);
if (order != SequenceFuture) {
@ -1088,9 +1063,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq)
m_stats.last_ping = round_time;
m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3;
s->outstanding_bytes -= iter->second.packet.Length();
iter = s->outstanding_packets.erase(iter);
ProcessOutboundQueue();
iter = s->sent_packets.erase(iter);
}
else {
++iter;
@ -1102,8 +1075,8 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
{
auto now = Clock::now();
auto s = &m_streams[stream];
auto iter = s->outstanding_packets.find(seq);
if (iter != s->outstanding_packets.end()) {
auto iter = s->sent_packets.find(seq);
if (iter != s->sent_packets.end()) {
uint64_t round_time = (uint64_t)std::chrono::duration_cast<std::chrono::milliseconds>(now - iter->second.last_sent).count();
m_stats.max_ping = std::max(m_stats.max_ping, round_time);
@ -1111,31 +1084,10 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq)
m_stats.last_ping = round_time;
m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3;
s->outstanding_bytes -= iter->second.packet.Length();
s->outstanding_packets.erase(iter);
ProcessOutboundQueue();
s->sent_packets.erase(iter);
}
}
void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent)
{
auto s = &m_streams[stream];
//If we can send the packet then send it
//else buffer it to be sent when we can send it
if (s->outstanding_bytes + sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || s->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) {
//Would go over one of the limits, buffer this packet.
DaybreakBufferedPacket bp;
bp.sent = std::move(sent);
bp.seq = seq;
s->buffered_packets.push_back(bp);
return;
}
s->outstanding_bytes += sent.packet.Length();
s->outstanding_packets.insert(std::make_pair(seq, sent));
InternalBufferedSend(sent.packet);
}
void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq)
{
DaybreakReliableHeader ack;
@ -1187,10 +1139,6 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p)
FlushBuffer();
}
if (m_buffered_packets.size() == 0) {
m_hold_time = Clock::now();
}
DynamicPacket copy;
copy.PutPacket(0, p);
m_buffered_packets.push_back(copy);
@ -1253,13 +1201,13 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p)
for (int i = 0; i < 2; ++i) {
switch (m_encode_passes[i]) {
case EncodeCompression:
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
break;
Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
break;
case EncodeXOR:
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
break;
Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size());
break;
default:
break;
break;
}
}
@ -1345,9 +1293,11 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
sent.last_sent = Clock::now();
sent.first_sent = Clock::now();
sent.times_resent = 0;
BufferPacket(stream_id, stream->sequence_out, sent);
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
stream->sequence_out++;
InternalBufferedSend(first_packet);
while (used < length) {
auto left = length - used;
DynamicPacket packet;
@ -1371,8 +1321,10 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
sent.last_sent = Clock::now();
sent.first_sent = Clock::now();
sent.times_resent = 0;
BufferPacket(stream_id, stream->sequence_out, sent);
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
stream->sequence_out++;
InternalBufferedSend(packet);
}
}
else {
@ -1389,8 +1341,10 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id,
sent.last_sent = Clock::now();
sent.first_sent = Clock::now();
sent.times_resent = 0;
BufferPacket(stream_id, stream->sequence_out, sent);
stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent));
stream->sequence_out++;
InternalBufferedSend(packet);
}
}

View File

@ -8,8 +8,7 @@
#include <functional>
#include <memory>
#include <map>
#include <unordered_map>
#include <deque>
#include <queue>
#include <list>
namespace EQ
@ -145,12 +144,6 @@ namespace EQ
size_t times_resent;
};
struct DaybreakBufferedPacket
{
uint16_t seq;
DaybreakSentPacket sent;
};
struct DaybreakStream
{
DaybreakStream() {
@ -158,20 +151,17 @@ namespace EQ
sequence_out = 0;
fragment_current_bytes = 0;
fragment_total_bytes = 0;
outstanding_bytes = 0;
}
uint16_t sequence_in;
uint16_t sequence_out;
std::unordered_map<uint16_t, Packet*> packet_queue;
std::deque<DaybreakBufferedPacket> buffered_packets;
std::map<uint16_t, Packet*> packet_queue;
DynamicPacket fragment_packet;
uint32_t fragment_current_bytes;
uint32_t fragment_total_bytes;
std::unordered_map<uint16_t, DaybreakSentPacket> outstanding_packets;
size_t outstanding_bytes;
std::map<uint16_t, DaybreakSentPacket> sent_packets;
};
DaybreakStream m_streams[4];
@ -179,8 +169,7 @@ namespace EQ
void Process();
void ProcessPacket(Packet &p);
void ProcessInboundQueue();
void ProcessOutboundQueue();
void ProcessQueue();
void RemoveFromQueue(int stream, uint16_t seq);
void AddToQueue(int stream, uint16_t seq, const Packet &p);
void ProcessDecodedPacket(const Packet &p);
@ -196,7 +185,6 @@ namespace EQ
void ProcessResend(int stream);
void Ack(int stream, uint16_t seq);
void OutOfOrderAck(int stream, uint16_t seq);
void BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent);
void SendConnect();
void SendKeepAlive();
@ -219,8 +207,8 @@ namespace EQ
keepalive_delay_ms = 9000;
resend_delay_ms = 150;
resend_delay_factor = 1.5;
resend_delay_min = 300;
resend_delay_max = 3000;
resend_delay_min = 150;
resend_delay_max = 1000;
connect_delay_ms = 500;
stale_connection_ms = 90000;
connect_stale_ms = 5000;
@ -236,8 +224,6 @@ namespace EQ
tic_rate_hertz = 60.0;
resend_timeout = 90000;
connection_close_time = 2000;
max_outstanding_packets = 400;
max_outstanding_bytes = 400 * 512;
}
size_t max_packet_size;
@ -260,8 +246,6 @@ namespace EQ
size_t connection_close_time;
DaybreakEncodeType encode_passes[2];
int port;
size_t max_outstanding_packets;
size_t max_outstanding_bytes;
};
class DaybreakConnectionManager