Skip to content

Commit

Permalink
add hash error analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
misternebula committed Feb 14, 2024
1 parent cb6b811 commit 6e04266
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 2 deletions.
66 changes: 66 additions & 0 deletions QSB/WorldSync/HashErrorAnalysis.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Collections.Generic;
using System.Linq;
using OWML.Common;
using QSB.Utility;
using QSB.Player.Messages;
using QSB.Messaging;
using QSB.Utility.Deterministic;

namespace QSB.WorldSync;

public class HashErrorAnalysis
{
public static Dictionary<string, HashErrorAnalysis> Instances = new();

private readonly string _managerName;

private readonly List<(string hash, string path)> _paths = new();

public HashErrorAnalysis(string managerName) => _managerName = managerName;

public void OnReceiveMessage(string deterministicPath) => _paths.Add((deterministicPath.GetMD5Hash(), deterministicPath));

public void AllDataSent(uint from)
{
var serverObjects = QSBWorldSync.GetWorldObjectsFromManager(_managerName);

var serverDetPaths = serverObjects.Select(x => x.AttachedObject.DeterministicPath());
var serverDetPathDict = serverDetPaths.Select(path => (path.GetMD5Hash(), path)).ToList<(string hash, string path)>();

var serverDoesNotHave = new List<string>();
var clientDoesNotHave = new List<string>();

foreach (var (hash, path) in serverDetPathDict)
{
if (!_paths.Any(x => x.hash == hash))
{
// client does not contain something from the server
clientDoesNotHave.Add(path);
}
}

foreach (var (hash, path) in _paths)
{
if (!serverDetPathDict.Any(x => x.hash == hash))
{
// client does not contain something from the server
serverDoesNotHave.Add(path);
}
}

DebugLog.ToConsole($"{_managerName} - Client is missing :", MessageType.Error);
foreach (var item in clientDoesNotHave)
{
DebugLog.ToConsole($"- {item}", MessageType.Error);
}

DebugLog.ToConsole($"{_managerName} - Client has extra :", MessageType.Error);
foreach (var item in serverDoesNotHave)
{
DebugLog.ToConsole($"- {item}", MessageType.Error);
}
Instances.Remove(_managerName);

new PlayerKickMessage(from, $"WorldObject hash error for {_managerName}").Send();
}
}
10 changes: 10 additions & 0 deletions QSB/WorldSync/Messages/DataDumpFinishedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using QSB.Messaging;

namespace QSB.WorldSync.Messages;

public class DataDumpFinishedMessage : QSBMessage<string>
{
public DataDumpFinishedMessage(string managerName) : base(managerName) => To = 0;

public override void OnReceiveRemote() => HashErrorAnalysis.Instances[Data].AllDataSent(From);
}
8 changes: 8 additions & 0 deletions QSB/WorldSync/Messages/HashCheckSucceededMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using QSB.Messaging;

namespace QSB.WorldSync.Messages;

internal class HashCheckSucceededMessage : QSBMessage
{

}
27 changes: 27 additions & 0 deletions QSB/WorldSync/Messages/RequestHashBreakdownMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using OWML.Common;
using QSB.Messaging;
using QSB.Utility;

namespace QSB.WorldSync.Messages;

/// <summary>
/// Sent to clients from the server when a client has an incorrect WorldObject hash.
/// </summary>
internal class RequestHashBreakdownMessage : QSBMessage<string>
{
public RequestHashBreakdownMessage(string managerName) : base(managerName) { }

public override void OnReceiveRemote()
{
DebugLog.ToConsole($"Received RequestHashBreakdownMessage for {Data}", MessageType.Error);
var objects = QSBWorldSync.GetWorldObjectsFromManager(Data);

foreach (var worldObject in objects)
{
new WorldObjectInfoMessage(worldObject, Data).Send();
}

DebugLog.ToConsole("- Sending finished message.", MessageType.Error);
new DataDumpFinishedMessage(Data).Send();
}
}
17 changes: 17 additions & 0 deletions QSB/WorldSync/Messages/WorldObjectInfoMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using QSB.Messaging;
using QSB.Utility.Deterministic;

namespace QSB.WorldSync.Messages;

/// <summary>
/// Sent by clients to the server after receiving a RequestHashBreakdown message.
/// </summary>
public class WorldObjectInfoMessage : QSBMessage<(string fullPath, string managerName)>
{
public WorldObjectInfoMessage(IWorldObject obj, string managerName) : base((obj.AttachedObject.DeterministicPath(), managerName)) => To = 0;

public override void OnReceiveRemote()
{
HashErrorAnalysis.Instances[Data.managerName].OnReceiveMessage(Data.fullPath);
}
}
10 changes: 8 additions & 2 deletions QSB/WorldSync/Messages/WorldObjectsHashMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,14 @@ public override void OnReceiveRemote()
if (hash != Data.hash)
{
// oh fuck oh no oh god
DebugLog.ToConsole($"Kicking {From} because their WorldObjects hash for {Data.managerName} is wrong. (Server:{hash} count:{count}, Client:{Data.hash} count:{Data.count})", MessageType.Error);
new PlayerKickMessage(From, $"WorldObject hash error for {Data.managerName}. (Server:{hash} count:{count}, Client:{Data.hash}, count:{Data.count})").Send();
/*DebugLog.ToConsole($"Kicking {From} because their WorldObjects hash for {Data.managerName} is wrong. (Server:{hash} count:{count}, Client:{Data.hash} count:{Data.count})", MessageType.Error);
new PlayerKickMessage(From, $"WorldObject hash error for {Data.managerName}. (Server:{hash} count:{count}, Client:{Data.hash}, count:{Data.count})").Send();*/
DebugLog.ToConsole($"{From} has an incorrect hash for {Data.managerName}. (S:{hash}:{count}, C:{Data.hash}-{Data.count}) Requesting data for analysis...", MessageType.Error);
HashErrorAnalysis.Instances.Add(Data.managerName, new HashErrorAnalysis(Data.managerName));
new RequestHashBreakdownMessage(Data.managerName) {To = From}.Send();
}
});
}
Expand Down

0 comments on commit 6e04266

Please sign in to comment.