summaryrefslogtreecommitdiff
path: root/Impostor-dev/src/Impostor.Tools.ServerReplay/Program.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Impostor-dev/src/Impostor.Tools.ServerReplay/Program.cs')
-rw-r--r--Impostor-dev/src/Impostor.Tools.ServerReplay/Program.cs195
1 files changed, 195 insertions, 0 deletions
diff --git a/Impostor-dev/src/Impostor.Tools.ServerReplay/Program.cs b/Impostor-dev/src/Impostor.Tools.ServerReplay/Program.cs
new file mode 100644
index 0000000..5aaa954
--- /dev/null
+++ b/Impostor-dev/src/Impostor.Tools.ServerReplay/Program.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Net;
+using System.Threading.Tasks;
+using Impostor.Api.Events.Managers;
+using Impostor.Api.Games;
+using Impostor.Api.Games.Managers;
+using Impostor.Api.Innersloth;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
+using Impostor.Api.Net.Messages.C2S;
+using Impostor.Hazel;
+using Impostor.Hazel.Extensions;
+using Impostor.Server.Events;
+using Impostor.Server.Net;
+using Impostor.Server.Net.Factories;
+using Impostor.Server.Net.Manager;
+using Impostor.Server.Net.Redirector;
+using Impostor.Server.Recorder;
+using Impostor.Tools.ServerReplay.Mocks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.ObjectPool;
+using Serilog;
+using ILogger = Serilog.ILogger;
+
+namespace Impostor.Tools.ServerReplay
+{
+ internal static class Program
+ {
+ private static readonly ILogger Logger = Log.ForContext(typeof(Program));
+ private static readonly Dictionary<int, IHazelConnection> Connections = new Dictionary<int, IHazelConnection>();
+ private static readonly Dictionary<int, GameOptionsData> GameOptions = new Dictionary<int, GameOptionsData>();
+
+ private static ServiceProvider _serviceProvider;
+
+ private static ObjectPool<MessageReader> _readerPool;
+ private static MockGameCodeFactory _gameCodeFactory;
+ private static ClientManager _clientManager;
+ private static GameManager _gameManager;
+
+ private static async Task Main(string[] args)
+ {
+ Log.Logger = new LoggerConfiguration()
+ // .MinimumLevel.Verbose()
+ .MinimumLevel.Debug()
+ .WriteTo.Console()
+ .CreateLogger();
+
+ var stopwatch = Stopwatch.StartNew();
+
+ foreach (var file in Directory.GetFiles(args[0]))
+ {
+ // Clear.
+ Connections.Clear();
+ GameOptions.Clear();
+
+ // Create service provider.
+ _serviceProvider = BuildServices();
+
+ // Create required instances.
+ _readerPool = _serviceProvider.GetRequiredService<ObjectPool<MessageReader>>();
+ _gameCodeFactory = _serviceProvider.GetRequiredService<MockGameCodeFactory>();
+ _clientManager = _serviceProvider.GetRequiredService<ClientManager>();
+ _gameManager = _serviceProvider.GetRequiredService<GameManager>();
+
+ await using (var stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
+ using (var reader = new BinaryReader(stream))
+ {
+ await ParseSession(reader);
+ }
+ }
+
+ var elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
+
+ Logger.Information($"Took {elapsedMilliseconds}ms.");
+ }
+
+ private static ServiceProvider BuildServices()
+ {
+ var services = new ServiceCollection();
+
+ services.AddLogging(builder =>
+ {
+ builder.ClearProviders();
+ builder.AddSerilog();
+ });
+
+ services.AddSingleton<GameManager>();
+ services.AddSingleton<IGameManager>(p => p.GetRequiredService<GameManager>());
+
+ services.AddSingleton<MockGameCodeFactory>();
+ services.AddSingleton<IGameCodeFactory>(p => p.GetRequiredService<MockGameCodeFactory>());
+
+ services.AddSingleton<ClientManager>();
+ services.AddSingleton<IClientFactory, ClientFactory<Client>>();
+ services.AddSingleton<INodeLocator, NodeLocatorNoOp>();
+ services.AddSingleton<IEventManager, EventManager>();
+
+ services.AddHazel();
+
+ return services.BuildServiceProvider();
+ }
+
+ private static async Task ParseSession(BinaryReader reader)
+ {
+ while (reader.BaseStream.Position < reader.BaseStream.Length)
+ {
+ var dataLength = reader.ReadInt32();
+ var data = reader.ReadBytes(dataLength - 4);
+
+ await using (var stream = new MemoryStream(data))
+ using (var readerInner = new BinaryReader(stream))
+ {
+ await ParsePacket(readerInner);
+ }
+ }
+ }
+
+ private static async Task ParsePacket(BinaryReader reader)
+ {
+ var dataType = (RecordedPacketType) reader.ReadByte();
+
+ // Read client id.
+ var clientId = reader.ReadInt32();
+
+ switch (dataType)
+ {
+ case RecordedPacketType.Connect:
+ // Read data.
+ var addressLength = reader.ReadByte();
+ var addressBytes = reader.ReadBytes(addressLength);
+ var addressPort = reader.ReadUInt16();
+ var address = new IPEndPoint(new IPAddress(addressBytes), addressPort);
+ var name = reader.ReadString();
+
+ // Create and register connection.
+ var connection = new MockHazelConnection(address);
+
+ await _clientManager.RegisterConnectionAsync(connection, name, 50516550);
+
+ // Store reference for ourselfs.
+ Connections.Add(clientId, connection);
+ break;
+
+ case RecordedPacketType.Disconnect:
+ string reason = null;
+
+ if (reader.BaseStream.Position < reader.BaseStream.Length)
+ {
+ reason = reader.ReadString();
+ }
+
+ await Connections[clientId].Client!.HandleDisconnectAsync(reason);
+ Connections.Remove(clientId);
+ break;
+
+ case RecordedPacketType.Message:
+ {
+ var messageType = (MessageType)reader.ReadByte();
+ var tag = reader.ReadByte();
+ var length = reader.ReadInt32();
+ var buffer = reader.ReadBytes(length);
+ using var message = _readerPool.Get();
+
+ message.Update(buffer, tag: tag);
+
+ if (tag == MessageFlags.HostGame)
+ {
+ GameOptions.Add(clientId, Message00HostGameC2S.Deserialize(message));
+ }
+ else if (Connections.TryGetValue(clientId, out var client))
+ {
+ await client.Client!.HandleMessageAsync(message, messageType);
+ }
+
+ break;
+ }
+
+ case RecordedPacketType.GameCreated:
+ _gameCodeFactory.Result = GameCode.From(reader.ReadString());
+
+ await _gameManager.CreateAsync(GameOptions[clientId]);
+
+ GameOptions.Remove(clientId);
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ }
+}