Compare commits

..

11 commits

9 changed files with 163 additions and 133 deletions

View file

@ -1,9 +1,9 @@
name: Release Rai.PacketMediator name: Release Rai.PacketMediator
run-name: ${{ gitea.actor }} is building the Server application run-name: ${{ gitea.actor }} is building the Server application
on: on:
push: push:
tags: tags:
- 'v*.*.*' - v*.*.*
paths-ignore: paths-ignore:
- .run/** - .run/**

View file

@ -8,12 +8,12 @@ repos:
entry: dotnet format --include entry: dotnet format --include
types_or: [c#, vb] types_or: [c#, vb]
- repo: https://github.com/Mateusz-Grzelinski/actionlint-py - repo: https://github.com/Mateusz-Grzelinski/actionlint-py
rev: v1.6.26.11 rev: v1.7.1.15
hooks: hooks:
- id: actionlint - id: actionlint
additional_dependencies: [pyflakes>=3.0.1, shellcheck-py>=0.9.0.5] additional_dependencies: [pyflakes>=3.0.1, shellcheck-py>=0.9.0.5]
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.12.0 rev: v2.14.0
hooks: hooks:
- id: pretty-format-yaml - id: pretty-format-yaml
args: [--autofix, --indent, '2'] args: [--autofix, --indent, '2']

View file

@ -0,0 +1,3 @@
// Licensed to Timothy Schenk under the Apache 2.0 License.
Console.WriteLine("Hello World!");

View file

@ -0,0 +1,8 @@
// Licensed to Timothy Schenk under the Apache 2.0 License.
namespace PacketMediator.Samples;
public class Sample
{
}

View file

@ -15,9 +15,9 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="FluentAssertions" Version="6.12.0" /> <PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageReference Include="xunit" Version="2.9.0" /> <PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7"> <PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View file

@ -23,12 +23,14 @@ public class PacketDistributor<TPacketIdEnum, TSession> where TPacketIdEnum : En
public PacketDistributor(IServiceProvider serviceProvider, public PacketDistributor(IServiceProvider serviceProvider,
IEnumerable<Assembly> sourcesContainingPackets, IEnumerable<Assembly> sourcesContainingPacketHandlers) IEnumerable<Assembly> sourcesContainingPackets, IEnumerable<Assembly> sourcesContainingPacketHandlers)
{ {
_channel = Channel.CreateUnbounded<ValueTuple<byte[], TPacketIdEnum, TSession>>(new UnboundedChannelOptions _channel = Channel.CreateUnbounded<ValueTuple<byte[], TPacketIdEnum, TSession>>(
new UnboundedChannelOptions
{ {
AllowSynchronousContinuations = false, AllowSynchronousContinuations = false,
SingleReader = false, SingleReader = false,
SingleWriter = false SingleWriter = false
}); }
);
var containingPackets = sourcesContainingPackets as Assembly[] ?? sourcesContainingPackets.ToArray(); var containingPackets = sourcesContainingPackets as Assembly[] ?? sourcesContainingPackets.ToArray();
var allIncomingPackets = GetAllPackets(containingPackets, typeof(IIncomingPacket)); var allIncomingPackets = GetAllPackets(containingPackets, typeof(IIncomingPacket));
var allOutgoingPackets = GetAllPackets(containingPackets, typeof(IOutgoingPacket)); var allOutgoingPackets = GetAllPackets(containingPackets, typeof(IOutgoingPacket));
@ -45,9 +47,11 @@ public class PacketDistributor<TPacketIdEnum, TSession> where TPacketIdEnum : En
{ {
var packetHandler = var packetHandler =
ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider, ActivatorUtilities.GetServiceOrCreateInstance(serviceProvider,
packetHandlerPair.Value); packetHandlerPair.Value
);
_packetHandlersInstantiation.TryAdd(packetHandlerPair.Key, packetHandler as IPacketHandler<TSession>); _packetHandlersInstantiation.TryAdd(packetHandlerPair.Key, packetHandler as IPacketHandler<TSession>);
}); }
);
allIncomingPackets.ForEach(packetsType => allIncomingPackets.ForEach(packetsType =>
{ {
var lambda = CodeGenerator.Lambda<Func<byte[], IIncomingPacket>>(fun => var lambda = CodeGenerator.Lambda<Func<byte[], IIncomingPacket>>(fun =>
@ -60,9 +64,12 @@ public class PacketDistributor<TPacketIdEnum, TSession> where TPacketIdEnum : En
CodeGenerator.Call(packetVariable, nameof(IIncomingPacket.Deserialize), argPacketData); CodeGenerator.Call(packetVariable, nameof(IIncomingPacket.Deserialize), argPacketData);
CodeGenerator.Return(packetVariable); CodeGenerator.Return(packetVariable);
}).Compile(); }
)
.Compile();
tempDeserializationMap.TryAdd(packetsType.Key, lambda); tempDeserializationMap.TryAdd(packetsType.Key, lambda);
}); }
);
_deserializationMap = tempDeserializationMap.ToImmutableDictionary(); _deserializationMap = tempDeserializationMap.ToImmutableDictionary();
} }
@ -74,11 +81,13 @@ public class PacketDistributor<TPacketIdEnum, TSession> where TPacketIdEnum : En
{ {
var packetsWithId = sourcesContainingPackets.SelectMany(a => a.GetTypes() var packetsWithId = sourcesContainingPackets.SelectMany(a => a.GetTypes()
.Where(type => type is { IsInterface: false, IsAbstract: false } && .Where(type => type is { IsInterface: false, IsAbstract: false } &&
type.GetInterfaces().Contains(packetType) type.GetInterfaces().Contains(packetType) &&
&& type.GetCustomAttributes<PacketIdAttribute<TPacketIdEnum>>().Any() type.GetCustomAttributes<PacketIdAttribute<TPacketIdEnum>>().Any()
)) )
)
.Select(type => .Select(type =>
new { Type = type, Attribute = type.GetCustomAttribute<PacketIdAttribute<TPacketIdEnum>>() }) new { Type = type, Attribute = type.GetCustomAttribute<PacketIdAttribute<TPacketIdEnum>>() }
)
.Select(x => new KeyValuePair<TPacketIdEnum, Type>(x.Attribute!.Code, x.Type)); .Select(x => new KeyValuePair<TPacketIdEnum, Type>(x.Attribute!.Code, x.Type));
return packetsWithId; return packetsWithId;
@ -89,20 +98,32 @@ public class PacketDistributor<TPacketIdEnum, TSession> where TPacketIdEnum : En
{ {
var packetHandlersWithId = sourcesContainingPacketHandlers.SelectMany(assembly => assembly.GetTypes() var packetHandlersWithId = sourcesContainingPacketHandlers.SelectMany(assembly => assembly.GetTypes()
.Where(t => .Where(t =>
t is { IsClass: true, IsAbstract: false } && Array.Exists(t t is { IsClass: true, IsAbstract: false } &&
.GetInterfaces(), i => Array.Exists(t
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<,>))) .GetInterfaces(),
i =>
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<,>)
)
)
.Select(packetHandlerType => new .Select(packetHandlerType => new
{ {
Type = packetHandlerType, Type = packetHandlerType,
PacketId = packetHandlerType PacketId = packetHandlerType
.GetInterfaces().First(t1 => .GetInterfaces()
.First(t1 =>
t1 is { IsGenericType: true } && t1 is { IsGenericType: true } &&
t1.GetGenericTypeDefinition() == typeof(IPacketHandler<,>)).GetGenericArguments() t1.GetGenericTypeDefinition() == typeof(IPacketHandler<,>)
.First(genericType => genericType.GetInterfaces().Any(packetType => )
packetType == typeof(IPacket))) .GetGenericArguments()
.First(genericType => genericType.GetInterfaces()
.Any(packetType =>
packetType == typeof(IPacket)
)
)
.GetCustomAttribute<PacketIdAttribute<TPacketIdEnum>>() .GetCustomAttribute<PacketIdAttribute<TPacketIdEnum>>()
})) }
)
)
.Where(x => x.PacketId != null) .Where(x => x.PacketId != null)
.Select(x => new KeyValuePair<TPacketIdEnum, Type>(x.PacketId!.Code, x.Type)); .Select(x => new KeyValuePair<TPacketIdEnum, Type>(x.PacketId!.Code, x.Type));

View file

@ -13,13 +13,15 @@ public class PacketDistributorService<TPacketIdEnum, TSession> : IHostedService
public PacketDistributorService(IServiceProvider serviceProvider, public PacketDistributorService(IServiceProvider serviceProvider,
IEnumerable<Assembly> sourcesContainingPackets, IEnumerable<Assembly> sourcesContainingPacketHandlers) IEnumerable<Assembly> sourcesContainingPackets, IEnumerable<Assembly> sourcesContainingPacketHandlers)
{ {
_packetDistributor = new PacketDistributor<TPacketIdEnum, TSession>(serviceProvider, sourcesContainingPackets, _packetDistributor = new PacketDistributor<TPacketIdEnum, TSession>(serviceProvider,
sourcesContainingPacketHandlers); sourcesContainingPackets,
sourcesContainingPacketHandlers
);
} }
public Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken)
{ {
return _packetDistributor.DequeuePacketAsync(cancellationToken); await _packetDistributor.DequeuePacketAsync(cancellationToken);
} }
public Task StopAsync(CancellationToken cancellationToken) public Task StopAsync(CancellationToken cancellationToken)
@ -32,15 +34,10 @@ public class PacketDistributorService<TPacketIdEnum, TSession> : IHostedService
return _packetDistributor.AddPacketAsync(packetData, operationCode, session); return _packetDistributor.AddPacketAsync(packetData, operationCode, session);
} }
public TPacketIdEnum GetOperationCodeByPacketType(IPacket packet) public DotNext.Optional<TPacketIdEnum> GetOperationCodeByPacketType(IPacket packet)
{ {
var type = packet.GetType(); var type = packet.GetType();
_packetDistributor.PacketIdMap.TryGetValue(type, out var value); _packetDistributor.PacketIdMap.TryGetValue(type, out var value);
if (value is null) return value ?? DotNext.Optional<TPacketIdEnum>.None;
{
throw new ArgumentOutOfRangeException(type.Name);
}
return value;
} }
} }

View file

@ -20,20 +20,21 @@
<PackageReadmeFile>README.md</PackageReadmeFile> <PackageReadmeFile>README.md</PackageReadmeFile>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<WarningsAsErrors>Nullable</WarningsAsErrors>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Include="../README.md" Pack="true" PackagePath="\"/> <None Include="../README.md" Pack="true" PackagePath="\"/>
<PackageReference Include="DotNext" Version="5.3.1"/> <PackageReference Include="DotNext" Version="5.3.1"/>
<PackageReference Include="DotNext.Metaprogramming" Version="5.3.0"/> <PackageReference Include="DotNext.Metaprogramming" Version="5.3.0"/>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/> <PackageReference Include="JetBrains.Annotations" Version="2024.2.0"/>
<PackageReference Include="Meziantou.Analyzer" Version="2.0.146"> <PackageReference Include="Meziantou.Analyzer" Version="2.0.146">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0"/> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1"/> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1"/>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.9.28"> <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.10.48">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View file

@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "8.0.203", "version": "8.0.303",
"rollForward": "latestMinor", "rollForward": "latestMinor",
"allowPrerelease": false "allowPrerelease": false
} }