Network: Extend post-desync frame sync history

Record sync state at various points throughout each frame
This commit is contained in:
Jonathan G Rennison
2023-08-28 15:17:53 +01:00
parent 8e755bf0c2
commit cdf1ff8d5a
13 changed files with 241 additions and 65 deletions

View File

@@ -1291,8 +1291,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_ERROR(Packet *p
DesyncExtraInfo info;
info.client_name = client_name;
info.client_id = this->client_id;
info.desync_frame_seed = this->desync_frame_seed;
info.desync_frame_state_checksum = this->desync_frame_state_checksum;
info.desync_frame_info = std::move(this->desync_frame_info);
CrashLog::DesyncCrashLog(&(this->desync_log), &server_desync_log, info);
this->SendDesyncLog(server_desync_log);
@@ -1336,32 +1335,58 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_DESYNC_MSG(Pack
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_DESYNC_SYNC_DATA(Packet *p)
{
uint32 frame = p->Recv_uint32();
uint32 count = p->Recv_uint32();
uint32 frame_count = p->Recv_uint32();
DEBUG(net, 2, "Received desync sync data: %u frames from %08X", count, frame);
DEBUG(net, 2, "Received desync sync data: %u frames", frame_count);
uint server_idx = UINT32_MAX;
for (uint i = 0; i < _network_server_sync_records->size(); i++) {
if ((*_network_server_sync_records)[i].frame == frame) {
server_idx = i;
break;
if (frame_count == 0 || _network_sync_record_counts.empty()) return NETWORK_RECV_STATUS_OKAY;
size_t record_count_offset = 0;
size_t record_offset = 0;
for (uint i = 0; i < frame_count; i++) {
uint32 item_count = p->Recv_uint32();
if (item_count == 0) continue;
uint32 local_item_count = 0;
uint32 frame = 0;
NetworkSyncRecordEvents event = NSRE_BEGIN;
for (uint j = 0; j < item_count; j++) {
if (j == 0) {
frame = p->Recv_uint32();
while (_network_sync_records[record_offset].frame != frame) {
if (record_count_offset == _network_sync_record_counts.size()) {
return NETWORK_RECV_STATUS_OKAY;
}
record_offset += _network_sync_record_counts[record_count_offset];
record_count_offset++;
}
local_item_count = _network_sync_record_counts[record_count_offset];
} else {
event = (NetworkSyncRecordEvents)p->Recv_uint32();
}
uint32 seed_1 = p->Recv_uint32();
uint64 state_checksum = p->Recv_uint64();
if (j == local_item_count) {
this->desync_frame_info = stdstr_fmt("Desync subframe count mismatch: extra client record: %08X, %s", frame, GetSyncRecordEventName(event));
return NETWORK_RECV_STATUS_OKAY;
}
const NetworkSyncRecord &record = _network_sync_records[record_offset + j];
if (j != 0 && record.frame != event) {
this->desync_frame_info = stdstr_fmt("Desync subframe event mismatch: %08X, client: %s != server: %s",
frame, GetSyncRecordEventName(event), GetSyncRecordEventName((NetworkSyncRecordEvents)record.frame));
return NETWORK_RECV_STATUS_OKAY;
}
if (seed_1 != record.seed_1 || state_checksum != record.state_checksum) {
this->desync_frame_info = stdstr_fmt("Desync subframe mismatch: %08X, %s%s%s",
frame, GetSyncRecordEventName(event), (seed_1 != record.seed_1) ? ", seed" : "", (state_checksum != record.state_checksum) ? ", state checksum" : "");
return NETWORK_RECV_STATUS_OKAY;
}
}
if (local_item_count > item_count) {
const NetworkSyncRecord &record = _network_sync_records[record_offset + item_count];
this->desync_frame_info = stdstr_fmt("Desync subframe count mismatch: extra server record: %08X, %s", frame, GetSyncRecordEventName((NetworkSyncRecordEvents)record.frame));
return NETWORK_RECV_STATUS_OKAY;
}
}
if (server_idx == UINT32_MAX) return NETWORK_RECV_STATUS_OKAY;
for (uint i = 0; i < count; i++) {
uint32 seed_1 = p->Recv_uint32();
uint64 state_checksum = p->Recv_uint64();
const NetworkSyncRecord &record = (*_network_server_sync_records)[server_idx];
if (record.frame != frame) break;
if (record.seed_1 != seed_1 && this->desync_frame_seed == 0) this->desync_frame_seed = frame;
if (record.state_checksum != state_checksum && this->desync_frame_state_checksum == 0) this->desync_frame_state_checksum = frame;
frame++;
server_idx = (server_idx + 1) % _network_server_sync_records->size();
}
return NETWORK_RECV_STATUS_OKAY;