From 879aafdb3aca7ebba88206efa406901fe9a7f4c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sat, 14 Jan 2023 22:17:29 +0100 Subject: [PATCH] feat: add basic anonymizer function --- src/Anonymizer/DefaultAnonymizer.cs | 105 +++++++++++++++ .../Extensions/ServiceCollectionExtensions.cs | 100 ++++++++++++++ src/Anonymizer/Filters/HeaderFilter.cs | 37 ++++++ src/Anonymizer/Filters/HeaderFilterOptions.cs | 12 ++ src/Anonymizer/Filters/IFilter.cs | 20 +++ src/Anonymizer/IAnonymizer.cs | 49 +++++++ src/Anonymizer/Movers/AbstractMover.cs | 25 ++++ src/Anonymizer/Movers/Basic/BsPacketMover.cs | 21 +++ .../Movers/Basic/CInfoPacketMover.cs | 23 ++++ .../Movers/Basic/CListPacketMover.cs | 20 +++ .../Movers/Basic/CModePacketMover.cs | 20 +++ .../Movers/Basic/CondPacketMover.cs | 20 +++ .../Movers/Basic/DropPacketMover.cs | 20 +++ src/Anonymizer/Movers/Basic/GetPacketMover.cs | 21 +++ .../Movers/Basic/GidxPacketMover.cs | 29 ++++ src/Anonymizer/Movers/Basic/InPacketMover.cs | 45 +++++++ src/Anonymizer/Movers/Basic/MvPacketMover.cs | 20 +++ .../Movers/Basic/NRunPacketMover.cs | 20 +++ src/Anonymizer/Movers/Basic/OutPacketMover.cs | 20 +++ .../Movers/Basic/PairyPacketMover.cs | 20 +++ .../Movers/Basic/PinitPacketMover.cs | 48 +++++++ src/Anonymizer/Movers/Basic/PstPacketMover.cs | 20 +++ .../Movers/Basic/RaidPacketMover.cs | 28 ++++ .../Movers/Basic/RbossPacketMover.cs | 20 +++ .../Movers/Basic/RdlstPacketMover.cs | 28 ++++ src/Anonymizer/Movers/Basic/SayPacketMover.cs | 20 +++ src/Anonymizer/Movers/Basic/StPacketMover.cs | 20 +++ src/Anonymizer/Movers/Basic/SuPacketMover.cs | 21 +++ src/Anonymizer/Movers/Basic/TwkPacketMover.cs | 23 ++++ src/Anonymizer/Movers/IMover.cs | 46 +++++++ src/Anonymizer/Movers/RegisteredMovers.cs | 56 ++++++++ src/Anonymizer/PacketInfo.cs | 16 +++ src/Anonymizer/PacketProcessor.cs | 124 ++++++++++++++++++ src/Anonymizer/ProcessedPacket.cs | 11 ++ src/Anonymizer/Sinks/FileSink.cs | 55 ++++++++ src/Anonymizer/Sinks/FileSinkOptions.cs | 11 ++ src/Anonymizer/Sinks/IPacketDestination.cs | 20 +++ src/Anonymizer/Sinks/IPacketSource.cs | 31 +++++ 38 files changed, 1245 insertions(+) create mode 100644 src/Anonymizer/DefaultAnonymizer.cs create mode 100644 src/Anonymizer/Extensions/ServiceCollectionExtensions.cs create mode 100644 src/Anonymizer/Filters/HeaderFilter.cs create mode 100644 src/Anonymizer/Filters/HeaderFilterOptions.cs create mode 100644 src/Anonymizer/Filters/IFilter.cs create mode 100644 src/Anonymizer/IAnonymizer.cs create mode 100644 src/Anonymizer/Movers/AbstractMover.cs create mode 100644 src/Anonymizer/Movers/Basic/BsPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/CInfoPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/CListPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/CModePacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/CondPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/DropPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/GetPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/GidxPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/InPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/MvPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/NRunPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/OutPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/PairyPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/PinitPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/PstPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/RaidPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/RbossPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/RdlstPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/SayPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/StPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/SuPacketMover.cs create mode 100644 src/Anonymizer/Movers/Basic/TwkPacketMover.cs create mode 100644 src/Anonymizer/Movers/IMover.cs create mode 100644 src/Anonymizer/Movers/RegisteredMovers.cs create mode 100644 src/Anonymizer/PacketInfo.cs create mode 100644 src/Anonymizer/PacketProcessor.cs create mode 100644 src/Anonymizer/ProcessedPacket.cs create mode 100644 src/Anonymizer/Sinks/FileSink.cs create mode 100644 src/Anonymizer/Sinks/FileSinkOptions.cs create mode 100644 src/Anonymizer/Sinks/IPacketDestination.cs create mode 100644 src/Anonymizer/Sinks/IPacketSource.cs diff --git a/src/Anonymizer/DefaultAnonymizer.cs b/src/Anonymizer/DefaultAnonymizer.cs new file mode 100644 index 0000000..626a4f6 --- /dev/null +++ b/src/Anonymizer/DefaultAnonymizer.cs @@ -0,0 +1,105 @@ +// +// DefaultAnonymizer.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Anonymizer; + +/// +public class DefaultAnonymizer : IAnonymizer +{ + private readonly Random _random; + private readonly HashSet _generated; + private readonly Dictionary _ids; + private readonly Dictionary _names; + + /// + /// Initializes a new instance of the class. + /// + public DefaultAnonymizer() + { + _random = new Random(); + _generated = new HashSet(); + _ids = new Dictionary(); + _names = new Dictionary(); + } + + /// + public string AnonymizeName(string name) + { + if (!_names.ContainsKey(name)) + { + var generatedName = string.Empty; + for (var i = 0; i < 10; i++) + { + generatedName += (char)_random.Next('A', 'Z'); + } + + _names[name] = generatedName; + } + + return _names[name]; + } + + /// + public long AnonymizeId(long id) + { + if (!_ids.ContainsKey(id)) + { + var generated = _random.Next(); + if (_generated.Contains(generated)) + { + return AnonymizeId(id); + } + + _ids[id] = generated; + _generated.Add(generated); + + } + + return _ids[id]; + } + + /// + public int AnonymizeId(int id) + { + if (!_ids.ContainsKey(id)) + { + var generated = _random.Next() & 0xFFFFFFFF; + if (_generated.Contains(generated)) + { + return AnonymizeId(id); + } + + _ids[id] = generated; + _generated.Add(generated); + + } + + return (int)_ids[id]; + } + + /// + public short AnonymizeId(short id) + { + if (!_ids.ContainsKey(id)) + { + var generated = _random.Next() & 0xFFFF; + if (_generated.Contains(generated)) + { + return AnonymizeId(id); + } + + _ids[id] = generated; + _generated.Add(generated); + + } + + return (short)_ids[id]; + } + + /// + public (long Id, string Name) Anonymize(long id, string name) + => (AnonymizeId(id), AnonymizeName(name)); +} \ No newline at end of file diff --git a/src/Anonymizer/Extensions/ServiceCollectionExtensions.cs b/src/Anonymizer/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..b23f98b --- /dev/null +++ b/src/Anonymizer/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,100 @@ +// +// ServiceCollectionExtensions.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Anonymizer.Filters; +using Anonymizer.Movers; +using Anonymizer.Movers.Basic; +using Microsoft.Extensions.DependencyInjection; +using NosSmooth.Packets; +using NosSmooth.Packets.Client; +using NosSmooth.Packets.Client.Inventory; +using NosSmooth.Packets.Server.Battle; +using NosSmooth.Packets.Server.Character; +using NosSmooth.Packets.Server.Chat; +using NosSmooth.Packets.Server.Entities; +using NosSmooth.Packets.Server.Families; +using NosSmooth.Packets.Server.Groups; +using NosSmooth.Packets.Server.Inventory; +using NosSmooth.Packets.Server.Login; +using NosSmooth.Packets.Server.Maps; +using NosSmooth.Packets.Server.Raids; +using NosSmooth.Packets.Server.UI; + +namespace Anonymizer.Extensions; + +/// +/// An extension methods for . +/// +public static class ServiceCollectionExtensions +{ + /// + /// Adds anonymizer's , 's default implementation, + /// and basic movers (moving entity ids and names). + /// + /// The service collection. + /// The same service collection. + public static IServiceCollection AddAnonymizer(this IServiceCollection serviceCollection) + => serviceCollection + .AddSingleton() + .AddSingleton() + .AddTransient() + .AddBasicMovers(); + + /// + /// Adds movers that move entity id and name. + /// + /// The service collection. + /// The same service collection. + public static IServiceCollection AddBasicMovers(this IServiceCollection serviceCollection) + => serviceCollection + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover() + .AddMover(); + + /// + /// Adds movers that move players morphs, classes, sex, stats, weapons. + /// + /// The service collection. + /// The same service collection. + public static IServiceCollection AddAdvancedMovers(this IServiceCollection serviceCollection) + { + return serviceCollection; + } + + /// + /// Add mover for the given type. + /// + /// The service collection. + /// The mover type. + /// The packet type. + /// The same service collection. + public static IServiceCollection AddMover(this IServiceCollection serviceCollection) + where TMover : class, IMover + where TPacket : class, IPacket + => serviceCollection + .Configure(rm => rm.AddMover()) + .AddTransient() + .AddTransient, TMover>(); +} \ No newline at end of file diff --git a/src/Anonymizer/Filters/HeaderFilter.cs b/src/Anonymizer/Filters/HeaderFilter.cs new file mode 100644 index 0000000..5fd8079 --- /dev/null +++ b/src/Anonymizer/Filters/HeaderFilter.cs @@ -0,0 +1,37 @@ +// +// HeaderFilter.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Extensions.Options; + +namespace Anonymizer.Filters; + +/// +public class HeaderFilter : IFilter +{ + private readonly HeaderFilterOptions _options; + + /// + /// Initializes a new instance of the class. + /// + /// The header filter options. + public HeaderFilter(IOptions options) + { + _options = options.Value; + } + + /// + public bool Filter(PacketInfo packetInfo) + { + var splitted = packetInfo.Packet.Split(' '); + if (splitted.Length < 1) + { + return true; + } + + var header = splitted[0]; + return !_options.RemoveHeaders.Contains(header); + } +} \ No newline at end of file diff --git a/src/Anonymizer/Filters/HeaderFilterOptions.cs b/src/Anonymizer/Filters/HeaderFilterOptions.cs new file mode 100644 index 0000000..ebc1b14 --- /dev/null +++ b/src/Anonymizer/Filters/HeaderFilterOptions.cs @@ -0,0 +1,12 @@ +// +// HeaderFilterOptions.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Anonymizer.Filters; + +public record HeaderFilterOptions +( + IReadOnlyList RemoveHeaders +); \ No newline at end of file diff --git a/src/Anonymizer/Filters/IFilter.cs b/src/Anonymizer/Filters/IFilter.cs new file mode 100644 index 0000000..290e25c --- /dev/null +++ b/src/Anonymizer/Filters/IFilter.cs @@ -0,0 +1,20 @@ +// +// IFilter.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Anonymizer.Filters; + +/// +/// Filters packet strings. +/// +public interface IFilter +{ + /// + /// Check the given string, return whether to keep it. + /// + /// The packet info to check. + /// Whether to keep the packet. + public bool Filter(PacketInfo packetInfo); +} \ No newline at end of file diff --git a/src/Anonymizer/IAnonymizer.cs b/src/Anonymizer/IAnonymizer.cs new file mode 100644 index 0000000..d1660be --- /dev/null +++ b/src/Anonymizer/IAnonymizer.cs @@ -0,0 +1,49 @@ +// +// IAnonymizer.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Anonymizer; + +/// +/// An anonymizer used in movers, to anonymize. +/// +public interface IAnonymizer +{ + /// + /// Anonymize the given name. + /// + /// The name to anonymize. + /// An anonymized name. + public string AnonymizeName(string name); + + /// + /// Anonymize the given id. + /// + /// The id to anonymize. + /// An anonymized id. + public long AnonymizeId(long id); + + /// + /// Anonymize the given id. + /// + /// The id to anonymize. + /// An anonymized id. + public int AnonymizeId(int id); + + /// + /// Anonymize the given id. + /// + /// The id to anonymize. + /// An anonymized id. + public short AnonymizeId(short id); + + /// + /// Anonymize id and a name. + /// + /// The id to anonymize. + /// The name to anonymize. + /// An anonymized tuple, name and id. + public (long Id, string Name) Anonymize(long id, string name); +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/AbstractMover.cs b/src/Anonymizer/Movers/AbstractMover.cs new file mode 100644 index 0000000..4769f5d --- /dev/null +++ b/src/Anonymizer/Movers/AbstractMover.cs @@ -0,0 +1,25 @@ +// +// AbstractMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets; + +namespace Anonymizer.Movers; + +/// +public abstract class AbstractMover : IMover + where TPacket : IPacket +{ + /// + public abstract TPacket Move(IAnonymizer anonymizer, TPacket packet); + + /// + public bool ShouldHandle(IPacket packet) + => packet is TPacket; + + /// + public IPacket Move(IAnonymizer anonymizer, IPacket packet) + => Move(anonymizer, (TPacket)packet); +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/BsPacketMover.cs b/src/Anonymizer/Movers/Basic/BsPacketMover.cs new file mode 100644 index 0000000..1ff7d08 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/BsPacketMover.cs @@ -0,0 +1,21 @@ +// +// BsPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Diagnostics; +using NosSmooth.Packets.Server.Battle; + +namespace Anonymizer.Movers.Basic; + +/// +public class BsPacketMover : AbstractMover +{ + /// + public override BsPacket Move(IAnonymizer anonymizer, BsPacket packet) + => packet with + { + CasterEntityId = anonymizer.AnonymizeId(packet.CasterEntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/CInfoPacketMover.cs b/src/Anonymizer/Movers/Basic/CInfoPacketMover.cs new file mode 100644 index 0000000..c2276b7 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/CInfoPacketMover.cs @@ -0,0 +1,23 @@ +// +// CInfoPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Character; + +namespace Anonymizer.Movers.Basic; + +/// +public class CInfoPacketMover : AbstractMover +{ + /// + public override CInfoPacket Move(IAnonymizer anonymizer, CInfoPacket packet) + => packet with + { + CharacterId = anonymizer.AnonymizeId(packet.CharacterId), + FamilyId = packet.FamilyId is null ? null : anonymizer.AnonymizeId(long.Parse(packet.FamilyId)).ToString(), + FamilyName = packet.FamilyName is null ? null : anonymizer.AnonymizeName(packet.FamilyName), + GroupId = packet.GroupId is null ? null : anonymizer.AnonymizeId(packet.GroupId.Value) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/CListPacketMover.cs b/src/Anonymizer/Movers/Basic/CListPacketMover.cs new file mode 100644 index 0000000..15b764c --- /dev/null +++ b/src/Anonymizer/Movers/Basic/CListPacketMover.cs @@ -0,0 +1,20 @@ +// +// CListPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Login; + +namespace Anonymizer.Movers.Basic; + +/// +public class CListPacketMover : AbstractMover +{ + /// + public override CListPacket Move(IAnonymizer anonymizer, CListPacket packet) + => packet with + { + Name = anonymizer.AnonymizeName(packet.Name) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/CModePacketMover.cs b/src/Anonymizer/Movers/Basic/CModePacketMover.cs new file mode 100644 index 0000000..e5130be --- /dev/null +++ b/src/Anonymizer/Movers/Basic/CModePacketMover.cs @@ -0,0 +1,20 @@ +// +// CModePacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Character; + +namespace Anonymizer.Movers.Basic; + +/// +public class CModePacketMover : AbstractMover +{ + /// + public override CModePacket Move(IAnonymizer anonymizer, CModePacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/CondPacketMover.cs b/src/Anonymizer/Movers/Basic/CondPacketMover.cs new file mode 100644 index 0000000..0859426 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/CondPacketMover.cs @@ -0,0 +1,20 @@ +// +// CondPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Entities; + +namespace Anonymizer.Movers.Basic; + +/// +public class CondPacketMover : AbstractMover +{ + /// + public override CondPacket Move(IAnonymizer anonymizer, CondPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/DropPacketMover.cs b/src/Anonymizer/Movers/Basic/DropPacketMover.cs new file mode 100644 index 0000000..202f517 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/DropPacketMover.cs @@ -0,0 +1,20 @@ +// +// DropPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Maps; + +namespace Anonymizer.Movers.Basic; + +/// +public class DropPacketMover : AbstractMover +{ + /// + public override DropPacket Move(IAnonymizer anonymizer, DropPacket packet) + => packet with + { + DropId = anonymizer.AnonymizeId(packet.DropId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/GetPacketMover.cs b/src/Anonymizer/Movers/Basic/GetPacketMover.cs new file mode 100644 index 0000000..2a7de9b --- /dev/null +++ b/src/Anonymizer/Movers/Basic/GetPacketMover.cs @@ -0,0 +1,21 @@ +// +// GetPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Client.Inventory; + +namespace Anonymizer.Movers.Basic; + +/// +public class GetPacketMover : AbstractMover +{ + /// + public override GetPacket Move(IAnonymizer anonymizer, GetPacket packet) + => packet with + { + GroundItemId = anonymizer.AnonymizeId(packet.GroundItemId), + PickerEntityId = anonymizer.AnonymizeId(packet.PickerEntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/GidxPacketMover.cs b/src/Anonymizer/Movers/Basic/GidxPacketMover.cs new file mode 100644 index 0000000..a2a7b2e --- /dev/null +++ b/src/Anonymizer/Movers/Basic/GidxPacketMover.cs @@ -0,0 +1,29 @@ +// +// GidxPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Families; +using NosSmooth.PacketSerializer.Abstractions.Common; + +namespace Anonymizer.Movers.Basic; + +/// +public class GidxPacketMover : AbstractMover +{ + /// + public override GidxPacket Move(IAnonymizer anonymizer, GidxPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId), + FamilyName = packet.FamilyName is null ? null : (NameString)anonymizer.AnonymizeName(packet.FamilyName.Name), + FamilySubPacket = packet.FamilySubPacket with + { + Value = packet.FamilySubPacket.Value is null ? null : packet.FamilySubPacket.Value with + { + FamilyId = anonymizer.AnonymizeName(packet.FamilySubPacket.Value.FamilyId) + } + } + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/InPacketMover.cs b/src/Anonymizer/Movers/Basic/InPacketMover.cs new file mode 100644 index 0000000..3f80ee4 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/InPacketMover.cs @@ -0,0 +1,45 @@ +// +// InPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Maps; +using NosSmooth.PacketSerializer.Abstractions.Common; + +namespace Anonymizer.Movers.Basic; + +/// +public class InPacketMover : AbstractMover +{ + /// + public override InPacket Move(IAnonymizer anonymizer, InPacket packet) + { + return packet with + { + EntityId = packet.EntityId, + Name = packet.Name is null ? null : (NameString)anonymizer.AnonymizeName(packet.Name), + PlayerSubPacket = packet.PlayerSubPacket is null + ? null + : packet.PlayerSubPacket with + { + GroupId = packet.PlayerSubPacket.GroupId is null + ? null + : anonymizer.AnonymizeId(packet.PlayerSubPacket.GroupId.Value), + FamilyName = packet.PlayerSubPacket.FamilyName is null + ? null + : anonymizer.AnonymizeName(packet.PlayerSubPacket.FamilyName), + FamilySubPacket = packet.PlayerSubPacket.FamilySubPacket with + { + Value = packet.PlayerSubPacket.FamilySubPacket.Value is null + ? null + : packet.PlayerSubPacket.FamilySubPacket.Value with + { + FamilyId = anonymizer.AnonymizeName + (packet.PlayerSubPacket.FamilySubPacket.Value.FamilyId) + } + } + } + }; + } +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/MvPacketMover.cs b/src/Anonymizer/Movers/Basic/MvPacketMover.cs new file mode 100644 index 0000000..b3e5c0a --- /dev/null +++ b/src/Anonymizer/Movers/Basic/MvPacketMover.cs @@ -0,0 +1,20 @@ +// +// MvPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Entities; + +namespace Anonymizer.Movers.Basic; + +/// +public class MvPacketMover : AbstractMover +{ + /// + public override MovePacket Move(IAnonymizer anonymizer, MovePacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/NRunPacketMover.cs b/src/Anonymizer/Movers/Basic/NRunPacketMover.cs new file mode 100644 index 0000000..04f4705 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/NRunPacketMover.cs @@ -0,0 +1,20 @@ +// +// NRunPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Client; + +namespace Anonymizer.Movers.Basic; + +/// +public class NRunPacketMover : AbstractMover +{ + /// + public override NRunPacket Move(IAnonymizer anonymizer, NRunPacket packet) + => packet with + { + EntityId = packet.EntityId + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/OutPacketMover.cs b/src/Anonymizer/Movers/Basic/OutPacketMover.cs new file mode 100644 index 0000000..4459f0b --- /dev/null +++ b/src/Anonymizer/Movers/Basic/OutPacketMover.cs @@ -0,0 +1,20 @@ +// +// OutPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Maps; + +namespace Anonymizer.Movers.Basic; + +/// +public class OutPacketMover : AbstractMover +{ + /// + public override OutPacket Move(IAnonymizer anonymizer, OutPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/PairyPacketMover.cs b/src/Anonymizer/Movers/Basic/PairyPacketMover.cs new file mode 100644 index 0000000..37c64a8 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/PairyPacketMover.cs @@ -0,0 +1,20 @@ +// +// PairyPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Inventory; + +namespace Anonymizer.Movers.Basic; + +/// +public class PairyPacketMover : AbstractMover +{ + /// + public override PairyPacket Move(IAnonymizer anonymizer, PairyPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/PinitPacketMover.cs b/src/Anonymizer/Movers/Basic/PinitPacketMover.cs new file mode 100644 index 0000000..09545b8 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/PinitPacketMover.cs @@ -0,0 +1,48 @@ +// +// PinitPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Groups; +using NosSmooth.PacketSerializer.Abstractions.Common; + +namespace Anonymizer.Movers.Basic; + +/// +public class PinitPacketMover : AbstractMover +{ + /// + public override PinitPacket Move(IAnonymizer anonymizer, PinitPacket packet) + { + return packet with + { + PinitSubPackets = packet.PinitSubPackets?.Select + ( + x => x with + { + EntityId = anonymizer.AnonymizeId(x.EntityId), + MateSubPacket = x.MateSubPacket is null + ? null + : x.MateSubPacket with + { + Name = x.MateSubPacket.Name is null + ? null + : (NameString)anonymizer.AnonymizeName(x.MateSubPacket.Name) + }, + PlayerSubPacket = x.PlayerSubPacket is null + ? null + : x.PlayerSubPacket with + { + GroupId = x.PlayerSubPacket.GroupId is null + ? null + : anonymizer.AnonymizeId(x.PlayerSubPacket.GroupId.Value), + Name = x.PlayerSubPacket.Name is null + ? null + : (NameString)anonymizer.AnonymizeName(x.PlayerSubPacket.Name) + } + } + ).ToArray() + }; + } +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/PstPacketMover.cs b/src/Anonymizer/Movers/Basic/PstPacketMover.cs new file mode 100644 index 0000000..a9f0969 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/PstPacketMover.cs @@ -0,0 +1,20 @@ +// +// PstPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Groups; + +namespace Anonymizer.Movers.Basic; + +/// +public class PstPacketMover : AbstractMover +{ + /// + public override PstPacket Move(IAnonymizer anonymizer, PstPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/RaidPacketMover.cs b/src/Anonymizer/Movers/Basic/RaidPacketMover.cs new file mode 100644 index 0000000..d1759f1 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/RaidPacketMover.cs @@ -0,0 +1,28 @@ +// +// RaidPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Raids; + +namespace Anonymizer.Movers.Basic; + +/// +public class RaidPacketMover : AbstractMover +{ + /// + public override RaidPacket Move(IAnonymizer anonymizer, RaidPacket packet) + => packet with + { + LeaderId = packet.LeaderId is null ? null : anonymizer.AnonymizeId(packet.LeaderId.Value), + ListMembersPlayerIds = packet.ListMembersPlayerIds?.Select(anonymizer.AnonymizeId).ToArray(), + PlayerHealths = packet.PlayerHealths?.Select + ( + x => x with + { + PlayerId = anonymizer.AnonymizeId(x.PlayerId) + } + ).ToArray() + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/RbossPacketMover.cs b/src/Anonymizer/Movers/Basic/RbossPacketMover.cs new file mode 100644 index 0000000..5592008 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/RbossPacketMover.cs @@ -0,0 +1,20 @@ +// +// RbossPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Raids; + +namespace Anonymizer.Movers.Basic; + +/// +public class RbossPacketMover : AbstractMover +{ + /// + public override RbossPacket Move(IAnonymizer anonymizer, RbossPacket packet) + => packet with + { + EntityId = packet.EntityId is null ? null : anonymizer.AnonymizeId(packet.EntityId.Value) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/RdlstPacketMover.cs b/src/Anonymizer/Movers/Basic/RdlstPacketMover.cs new file mode 100644 index 0000000..296f839 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/RdlstPacketMover.cs @@ -0,0 +1,28 @@ +// +// RdlstPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Raids; + +namespace Anonymizer.Movers.Basic; + +/// +public class RdlstPacketMover : AbstractMover +{ + /// + public override RdlstPacket Move(IAnonymizer anonymizer, RdlstPacket packet) + => packet with + { + Players = packet.Players.Select + ( + p => p with + { + Id = anonymizer.AnonymizeId(p.Id), + Name = anonymizer.AnonymizeName(p.Name) + } + ) + .ToArray() + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/SayPacketMover.cs b/src/Anonymizer/Movers/Basic/SayPacketMover.cs new file mode 100644 index 0000000..ec73356 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/SayPacketMover.cs @@ -0,0 +1,20 @@ +// +// SayPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Chat; + +namespace Anonymizer.Movers.Basic; + +/// +public class SayPacketMover : AbstractMover +{ + /// + public override SayPacket Move(IAnonymizer anonymizer, SayPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/StPacketMover.cs b/src/Anonymizer/Movers/Basic/StPacketMover.cs new file mode 100644 index 0000000..4dcc853 --- /dev/null +++ b/src/Anonymizer/Movers/Basic/StPacketMover.cs @@ -0,0 +1,20 @@ +// +// StPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Entities; + +namespace Anonymizer.Movers.Basic; + +/// +public class StPacketMover : AbstractMover +{ + /// + public override StPacket Move(IAnonymizer anonymizer, StPacket packet) + => packet with + { + EntityId = anonymizer.AnonymizeId(packet.EntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/SuPacketMover.cs b/src/Anonymizer/Movers/Basic/SuPacketMover.cs new file mode 100644 index 0000000..143c00e --- /dev/null +++ b/src/Anonymizer/Movers/Basic/SuPacketMover.cs @@ -0,0 +1,21 @@ +// +// SuPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.Battle; + +namespace Anonymizer.Movers.Basic; + +/// +public class SuPacketMover : AbstractMover +{ + /// + public override SuPacket Move(IAnonymizer anonymizer, SuPacket packet) + => packet with + { + CasterEntityId = anonymizer.AnonymizeId(packet.CasterEntityId), + TargetEntityId = anonymizer.AnonymizeId(packet.TargetEntityId) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/Basic/TwkPacketMover.cs b/src/Anonymizer/Movers/Basic/TwkPacketMover.cs new file mode 100644 index 0000000..cd3260d --- /dev/null +++ b/src/Anonymizer/Movers/Basic/TwkPacketMover.cs @@ -0,0 +1,23 @@ +// +// TwkPacketMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets.Server.UI; + +namespace Anonymizer.Movers.Basic; + +/// +public class TwkPacketMover : AbstractMover +{ + /// + public override TwkPacket Move(IAnonymizer anonymizer, TwkPacket packet) + => packet with + { + AccountName = anonymizer.AnonymizeName(packet.AccountName), + CharacterName = anonymizer.AnonymizeName(packet.CharacterName), + EntityId = anonymizer.AnonymizeId(packet.EntityId), + Salt = anonymizer.AnonymizeName(packet.Salt) + }; +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/IMover.cs b/src/Anonymizer/Movers/IMover.cs new file mode 100644 index 0000000..87e2661 --- /dev/null +++ b/src/Anonymizer/Movers/IMover.cs @@ -0,0 +1,46 @@ +// +// IMover.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets; + +namespace Anonymizer.Movers; + +/// +/// Moves a packet, anonymizes it. +/// +public interface IMover +{ + /// + /// Check whether to handle given packet. + /// + /// The packet to check. + /// Whether to handle that packet. + public bool ShouldHandle(IPacket packet); + + /// + /// Move the packet, anonymize it. + /// + /// The anonymizer to use. + /// The packet. + /// Moved packet. + public IPacket Move(IAnonymizer anonymizer, IPacket packet); +} + +/// +/// Moves a packet, anonymizes it. +/// +/// The type of the packet. +public interface IMover : IMover + where TPacket : IPacket +{ + /// + /// Move the packet, anonymize it. + /// + /// The anonymizer. + /// The packet to anonymize. + /// The new packet. + public TPacket Move(IAnonymizer anonymizer, TPacket packet); +} \ No newline at end of file diff --git a/src/Anonymizer/Movers/RegisteredMovers.cs b/src/Anonymizer/Movers/RegisteredMovers.cs new file mode 100644 index 0000000..a482ec7 --- /dev/null +++ b/src/Anonymizer/Movers/RegisteredMovers.cs @@ -0,0 +1,56 @@ +// +// RegisteredMovers.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Reflection; +using Microsoft.Extensions.Options; +using NosSmooth.Packets; +using NosSmooth.PacketSerializer.Abstractions.Attributes; + +namespace Anonymizer.Movers; + +/// +/// A class containing all of the registered movers, +/// initialized as +/// by the service extension methods. Used inside of +/// . +/// +public class RegisteredMovers +{ + private readonly HashSet _packetHeaders; + + /// + /// Initializes a new instance of the class. + /// + public RegisteredMovers() + { + _packetHeaders = new HashSet(); + } + + /// + /// Add the given mover packet type. + /// + /// The packet to add. + public void AddMover() + where TPacket : IPacket + { + var header = typeof(TPacket).GetCustomAttribute(); + + if (header?.Identifier is not null) + { + _packetHeaders.Add(header.Identifier); + } + } + + /// + /// Checks whether the given packet header has a mover registered. + /// + /// The packet header. + /// Whether to try to move the packet. + public bool ShouldMove(string packetHeader) + { + return _packetHeaders.Contains(packetHeader); + } +} \ No newline at end of file diff --git a/src/Anonymizer/PacketInfo.cs b/src/Anonymizer/PacketInfo.cs new file mode 100644 index 0000000..e915059 --- /dev/null +++ b/src/Anonymizer/PacketInfo.cs @@ -0,0 +1,16 @@ +// +// PacketInfo.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.PacketSerializer.Abstractions.Attributes; + +namespace Anonymizer; + +/// +/// Information about a packet. +/// +/// +/// +public record PacketInfo(PacketSource Source, string Packet); \ No newline at end of file diff --git a/src/Anonymizer/PacketProcessor.cs b/src/Anonymizer/PacketProcessor.cs new file mode 100644 index 0000000..b57f204 --- /dev/null +++ b/src/Anonymizer/PacketProcessor.cs @@ -0,0 +1,124 @@ +// +// PacketProcessor.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Diagnostics; +using Anonymizer.Filters; +using Anonymizer.Movers; +using Anonymizer.Sinks; +using Microsoft.Extensions.Options; +using NosSmooth.Packets; +using NosSmooth.PacketSerializer; +using NosSmooth.PacketSerializer.Abstractions.Attributes; +using Remora.Results; + +namespace Anonymizer; + +/// +/// Processes packets, anonymizes or filters them. +/// +public class PacketProcessor +{ + private readonly IPacketSerializer _packetSerializer; + private readonly IAnonymizer _anonymizer; + private readonly RegisteredMovers _registeredMovers; + private readonly IReadOnlyList _filters; + private readonly IReadOnlyList _movers; + + /// + /// Initializes a new instance of the class. + /// + /// The packet serializer. + /// The anonymizer. + /// The filters. + /// The movers. + /// The registered movers. + public PacketProcessor + ( + IPacketSerializer packetSerializer, + IAnonymizer anonymizer, + IEnumerable filters, + IEnumerable movers, + IOptions registeredMovers + ) + { + _packetSerializer = packetSerializer; + _anonymizer = anonymizer; + _registeredMovers = registeredMovers.Value; + _filters = filters.ToList(); + _movers = movers.ToList(); + } + + /// + /// Process one packet, anonymize it. + /// + /// The packet to anonymize. + /// The processed packet. + public Result ProcessPacket(PacketInfo packetInfo) + { + foreach (var filter in _filters) + { + if (!filter.Filter(packetInfo)) + { + return new ProcessedPacket(packetInfo.Packet, packetInfo.Packet, false); + } + } + + var header = packetInfo.Packet.Split(' ')[0]; + if (!_registeredMovers.ShouldMove(header)) + { + return new ProcessedPacket(packetInfo.Packet, packetInfo.Packet, true); + } + + var packetResult = _packetSerializer.Deserialize(packetInfo.Packet, packetInfo.Source); + if (!packetResult.IsDefined(out var packet)) + { + return Result.FromError(packetResult); + } + + foreach (var mover in _movers) + { + if (mover.ShouldHandle(packet)) + { + var movedPacket = mover.Move(_anonymizer, packet); + var serializedResult = _packetSerializer.Serialize(movedPacket); + if (!serializedResult.IsDefined(out var serialized)) + { + return Result.FromError(serializedResult); + } + + return new ProcessedPacket(packetInfo.Packet, serialized, true); + } + } + + return new ProcessedPacket(packetInfo.Packet, packetInfo.Packet, true); + } + + /// + /// Process the whole source and put the processed packets into the given destination. + /// + /// The source to get packets from. + /// The destination to put processed packets into. + /// The cancellation token for cancelling the operation. + /// A representing the asynchronous operation. + public async Task ProcessSourceDestination(IPacketSource source, IPacketDestination destination, CancellationToken ct = default) + { + while (await source.TryGetNextPacketAsync(out var packet, ct)) + { + var processedPacketResult = ProcessPacket(packet!); + if (!processedPacketResult.IsDefined(out var processedPacket)) + { + return Result.FromError(processedPacketResult); + } + + if (processedPacket.Keep) + { + await destination.WritePacketAsync(processedPacket.NewPacketString); + } + } + + return Result.FromSuccess(); + } +} \ No newline at end of file diff --git a/src/Anonymizer/ProcessedPacket.cs b/src/Anonymizer/ProcessedPacket.cs new file mode 100644 index 0000000..8bf1984 --- /dev/null +++ b/src/Anonymizer/ProcessedPacket.cs @@ -0,0 +1,11 @@ +// +// ProcessedPacket.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Packets; + +namespace Anonymizer; + +public record ProcessedPacket(string OriginalPacketString, string NewPacketString, bool Keep); \ No newline at end of file diff --git a/src/Anonymizer/Sinks/FileSink.cs b/src/Anonymizer/Sinks/FileSink.cs new file mode 100644 index 0000000..7999227 --- /dev/null +++ b/src/Anonymizer/Sinks/FileSink.cs @@ -0,0 +1,55 @@ +// +// FileSink.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Text.RegularExpressions; +using NosSmooth.PacketSerializer.Abstractions.Attributes; + +namespace Anonymizer.Sinks; + +/// +/// A sink that supports reading from a file and writing to a file. +/// +public class FileSink : IDisposable, IPacketSource, IPacketDestination +{ + private readonly FileSinkOptions _options; + private readonly FileStream _sourceStream; + private readonly FileStream _destinationStream; + + /// + /// Initializes a new instance of the class. + /// + /// The source file path. + /// The destination file path. + /// The options. + public FileSink(string sourceFile, string destinationFile, FileSinkOptions options) + { + _options = options; + _sourceStream = File.OpenRead(sourceFile); + _destinationStream = File.OpenWrite(destinationFile); + } + + /// + public long Cursor { get; private set; } + + /// + public Task TryGetNextPacketAsync(out PacketInfo packetInfo, CancellationToken ct = default) + { + throw new NotImplementedException(); + } + + /// + public Task WritePacketAsync(string packetString) + { + throw new NotImplementedException(); + } + + /// + public void Dispose() + { + _sourceStream.Dispose(); + _destinationStream.Dispose(); + } +} \ No newline at end of file diff --git a/src/Anonymizer/Sinks/FileSinkOptions.cs b/src/Anonymizer/Sinks/FileSinkOptions.cs new file mode 100644 index 0000000..149869f --- /dev/null +++ b/src/Anonymizer/Sinks/FileSinkOptions.cs @@ -0,0 +1,11 @@ +// +// FileSinkOptions.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Text.RegularExpressions; + +namespace Anonymizer.Sinks; + +public record FileSinkOptions(Regex lineRegex, string recvString, string sendString); \ No newline at end of file diff --git a/src/Anonymizer/Sinks/IPacketDestination.cs b/src/Anonymizer/Sinks/IPacketDestination.cs new file mode 100644 index 0000000..2e355e7 --- /dev/null +++ b/src/Anonymizer/Sinks/IPacketDestination.cs @@ -0,0 +1,20 @@ +// +// IPacketDestination.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Anonymizer.Sinks; + +/// +/// An interface for sending packets to an arbitrary destination. +/// +public interface IPacketDestination +{ + /// + /// Write the given packet string into the destination. + /// + /// The packet string to write. + /// A representing the asynchronous operation. + public Task WritePacketAsync(string packetString); +} \ No newline at end of file diff --git a/src/Anonymizer/Sinks/IPacketSource.cs b/src/Anonymizer/Sinks/IPacketSource.cs new file mode 100644 index 0000000..dc03a9f --- /dev/null +++ b/src/Anonymizer/Sinks/IPacketSource.cs @@ -0,0 +1,31 @@ +// +// IPacketSource.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Diagnostics.CodeAnalysis; + +namespace Anonymizer.Sinks; + +/// +/// An interface for receiving packets from an arbitrary source. +/// +public interface IPacketSource +{ + /// + /// The current cursor position (current packet index). + /// + public long Cursor { get; } + + /// + /// Tries to get next packet, if there is any. + /// + /// + /// Moves the cursor. + /// + /// The information about next packet. + /// The cancellation token used for cancelling the operation. + /// Whether next packet was loaded and cursor moved. If false, there are no more packets. + public Task TryGetNextPacketAsync([NotNullWhen(true)] out PacketInfo? packetInfo, CancellationToken ct = default); +} \ No newline at end of file -- 2.48.1