style: apply editorconfig style

This commit is contained in:
Timothy Schenk 2023-08-11 11:31:30 +02:00
parent 81829e87cb
commit 1de07e546a
22 changed files with 236 additions and 261 deletions

View file

@ -21,29 +21,24 @@ public class BinaryConversionBenchmarks
[GlobalSetup]
public void Setup()
{
data = RandomNumberGenerator.GetBytes(4000);
offset = RandomNumberGenerator.GetInt32(0, 3500);
this.data = RandomNumberGenerator.GetBytes(4000);
this.offset = RandomNumberGenerator.GetInt32(0, 3500);
}
[Benchmark]
public Int16 BitConverterTest()
{
return BitConverter.ToInt16(data, offset);
}
public short BitConverterTest() => BitConverter.ToInt16(this.data, this.offset);
[Benchmark]
public Int16 BinaryReader()
public short BinaryReader()
{
using MemoryStream ms = new MemoryStream(data);
using BinaryReader reader = new BinaryReader(ms);
reader.BaseStream.Position = offset;
using var ms = new MemoryStream(this.data);
using var reader = new BinaryReader(ms);
reader.BaseStream.Position = this.offset;
return reader.ReadInt16();
}
[Benchmark]
public Int16 BinaryPrimitives()
{
return System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian(
new ArraySegment<byte>(data, offset, sizeof(short)));
}
public short BinaryPrimitives() =>
System.Buffers.Binary.BinaryPrimitives.ReadInt16LittleEndian(
new ArraySegment<byte>(this.data, this.offset, sizeof(short)));
}

View file

@ -5,8 +5,5 @@ namespace Benchmarks;
internal class Program
{
public static void Main(string[] args)
{
BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
}
public static void Main(string[] args) => BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
}

View file

@ -15,26 +15,30 @@ public class AuthSession : TcpSession
public AuthSession(TcpServer
server, IMediator mediator, ILogger<AuthSession> logger) : base(server)
{
_mediator = mediator;
_logger = logger;
this._mediator = mediator;
this._logger = logger;
}
public override long Send(byte[] buffer)
{
_logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer));
this._logger.LogInformation("Data being sent is: {Data}", BitConverter.ToString(buffer));
return base.Send(buffer);
}
public void Send(IPacket packet)
{
var type = packet.GetType();
_logger.LogTrace("Packet of type {Type} is being serialized", type.Name);
this._logger.LogTrace("Packet of type {Type} is being serialized", type.Name);
var packetIdAttribute = type.GetCustomAttribute<PacketId>();
if (packetIdAttribute == null) return;
if (packetIdAttribute == null)
{
return;
}
var opcode = packetIdAttribute.Code;
Span<byte> packetData = packet.Serialize();
ushort length = (ushort)(packetData.Length + 8);
var length = (ushort)(packetData.Length + 8);
Span<byte> buffer = stackalloc byte[length];
buffer.Clear();
@ -42,20 +46,20 @@ public class AuthSession : TcpSession
var bytesOfLength = BitConverter.GetBytes(length);
var bytesOfOpcode = BitConverter.GetBytes((ushort)opcode);
for (int i = 0; i < bytesOfLength.Length || i < 2; i++)
for (var i = 0; i < bytesOfLength.Length || i < 2; i++)
{
buffer[i] = bytesOfLength[i];
}
for (int i = 0; i < bytesOfOpcode.Length || i < 2; i++)
for (var i = 0; i < bytesOfOpcode.Length || i < 2; i++)
{
buffer[2 + i] = bytesOfOpcode[i];
}
_logger.LogTrace("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray()));
_logger.LogTrace("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray()));
this._logger.LogTrace("Packet data being parsed is: {Data}", BitConverter.ToString(packetData.ToArray()));
this._logger.LogTrace("Packet being parsed is: {Data}", BitConverter.ToString(buffer.ToArray()));
Send(buffer);
this.Send(buffer);
}
protected override void OnReceived(byte[] buffer, long offset, long size)
@ -64,7 +68,7 @@ public class AuthSession : TcpSession
Span<byte> decryptedBuffer = new byte[size];
// xor every value after the first 8 bytes
var dataBuffer = Decrypt(new ArraySegment<byte>(buffer, 8, (int)size - 8).ToArray());
var dataBuffer = this.Decrypt(new ArraySegment<byte>(buffer, 8, (int)size - 8).ToArray());
Console.WriteLine("Length " + BitConverter.ToUInt16(buffer, 0));
var opCode = BitConverter.ToUInt16(buffer.ToArray(), 2);
@ -76,17 +80,16 @@ public class AuthSession : TcpSession
Console.WriteLine("Full buffer: " + Encoding.ASCII.GetString(dataBuffer.ToArray()));
RawPacket rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[0],
buffer[3],
Id, this);
Task.Run(() => _mediator.Send(rawPacket));
_logger.LogInformation("Connection from: {@RemoteEndpoint}", Socket.RemoteEndPoint?.ToString());
var rawPacket = new RawPacket((OperationCode)opCode, dataBuffer, clientAliveTime, buffer[0],
buffer[3], this.Id, this);
Task.Run(() => this._mediator.Send(rawPacket));
this._logger.LogInformation("Connection from: {@RemoteEndpoint}", this.Socket.RemoteEndPoint?.ToString());
base.OnReceived(decryptedBuffer.ToArray(), offset, decryptedBuffer.Length);
}
private byte[] Decrypt(byte[] buffer)
{
for (int i = 0; i < buffer.Length; ++i)
for (var i = 0; i < buffer.Length; ++i)
{
buffer[i] = (byte)(buffer[i] ^ i ^ (3 * (0xFE - i)));
}

View file

@ -15,31 +15,33 @@ public class ChannelSession : TcpSession
.Reverse().ToArray();
private static readonly byte[] IV = new byte[]
{ 0xfe, 220, 0xba, 0x98, 0x76, 0x54, 50, 0x10, 15, 30, 0x2d, 60, 0x4b, 90, 0x69, 120 }.Reverse().ToArray();
{
0xfe, 220, 0xba, 0x98, 0x76, 0x54, 50, 0x10, 15, 30, 0x2d, 60, 0x4b, 90, 0x69, 120
}.Reverse().ToArray();
private readonly ICryptoTransform _encryptor;
private readonly ICryptoTransform _decryptor;
public ChannelSession(TcpServer server, IMediator mediator, ILogger<ChannelSession> logger) : base(server)
{
_mediator = mediator;
_logger = logger;
this._mediator = mediator;
this._logger = logger;
var aes = Aes.Create();
aes.Key = Key;
aes.IV = IV;
aes.Padding = PaddingMode.None;
aes.Mode = CipherMode.ECB;
_decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
_encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
this._decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
this._encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
}
protected override void OnReceived(byte[] buffer, long offset, long size)
{
try
{
using (var ms = new MemoryStream(Decrypt(buffer)))
using (var cs = new CryptoStream(ms, _decryptor, CryptoStreamMode.Read))
using (var ms = new MemoryStream(this.Decrypt(buffer)))
using (var cs = new CryptoStream(ms, this._decryptor, CryptoStreamMode.Read))
{
cs.Read(buffer);
}
@ -48,14 +50,14 @@ public class ChannelSession : TcpSession
}
catch (CryptographicException ex)
{
_logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
_logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
this._logger.LogError("An error has occured while decrypting: {ErrorMessage}", ex.Message);
this._logger.LogError("Default buffer message: {Message}", Encoding.ASCII.GetString(buffer));
}
}
private byte[] Decrypt(byte[] buffer)
{
for (int i = 0; i < buffer.Length; ++i)
for (var i = 0; i < buffer.Length; ++i)
{
buffer[i] = (byte)(buffer[i] ^ i ^ (3 * (0xFE - i)));
}

View file

@ -8,14 +8,11 @@ public class PacketConsumer : IConsumer<RawPacket>
{
private readonly PacketDistributorService _distributorService;
public PacketConsumer(PacketDistributorService distributorService)
{
_distributorService = distributorService;
}
public PacketConsumer(PacketDistributorService distributorService) => this._distributorService = distributorService;
public Task Consume(ConsumeContext<RawPacket> context)
{
_distributorService.AddPacket(context.Message);
this._distributorService.AddPacket(context.Message);
return Task.CompletedTask;
}
}

View file

@ -6,10 +6,10 @@ public class Account : CouchDocument
{
public Account(string username, string password, string email, byte permissionLevel)
{
Username = username;
Password = password;
Email = email;
PermissionLevel = permissionLevel;
this.Username = username;
this.Password = password;
this.Email = email;
this.PermissionLevel = permissionLevel;
}
public string Username { get; private set; }

View file

@ -16,42 +16,35 @@ public class LoginHandler : IPacketHandler<LoginInfoPacket>
public LoginHandler(ILogger<LoginHandler> logger, WonderkingContext wonderkingContext, IConfiguration configuration)
{
_logger = logger;
_wonderkingContext = wonderkingContext;
_configuration = configuration;
this._logger = logger;
this._wonderkingContext = wonderkingContext;
this._configuration = configuration;
}
public async Task HandleAsync(LoginInfoPacket packet, TcpSession session)
{
_logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username,
this._logger.LogInformation("Login data: Username {Username} & Password {Password}", packet.Username,
packet.Password);
var account = _wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
var account = this._wonderkingContext.Accounts.FirstOrDefault(a => a.Username == packet.Username);
if (account == null)
{
if (_configuration.GetSection("Testing").GetValue<bool>("CreateAccountOnLogin"))
if (this._configuration.GetSection("Testing").GetValue<bool>("CreateAccountOnLogin"))
{
var result = _wonderkingContext.Accounts.AddAsync(new Account(packet.Username, packet.Password, "", 0));
var result =
this._wonderkingContext.Accounts.AddAsync(new Account(packet.Username, packet.Password, "", 0));
await result;
}
else
{
// TODO: Send Message that account does not exist
_logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username);
this._logger.LogInformation("Requested account for user: {Username} does not exist", packet.Username);
}
}
var loginResponsePacket = new LoginResponsePacket
{
LoginResponseReason = LoginResponseReason.OK,
ChannelData = new[]
{
new ServerChannelData
{
ChannelId = 0,
LoadPercentage = 200,
ServerId = 0
}
},
ChannelData = new[] { new ServerChannelData { ChannelId = 0, LoadPercentage = 200, ServerId = 0 } },
UnknownFlag = 1,
IsGameMaster = true
};

View file

@ -11,21 +11,21 @@ public class LoginInfoPacket : IPacket
public void Deserialize(byte[] data)
{
Username = Encoding.ASCII.GetString(data, 0, 20);
Password = Encoding.ASCII.GetString(data, 20, 31);
this.Username = Encoding.ASCII.GetString(data, 0, 20);
this.Password = Encoding.ASCII.GetString(data, 20, 31);
}
public byte[] Serialize()
{
Span<byte> dataSpan = stackalloc byte[20 + 31];
var usernameBytes = Encoding.ASCII.GetBytes(Username);
var passwordBytes = Encoding.ASCII.GetBytes(Password);
for (int i = 0; i < 20 || i < Username.Length; i++)
var usernameBytes = Encoding.ASCII.GetBytes(this.Username);
var passwordBytes = Encoding.ASCII.GetBytes(this.Password);
for (var i = 0; i < 20 || i < this.Username.Length; i++)
{
dataSpan[i] = usernameBytes[i];
}
for (int i = 0; i < 31 || i < Password.Length; i++)
for (var i = 0; i < 31 || i < this.Password.Length; i++)
{
dataSpan[20 + i] = passwordBytes[i];
}

View file

@ -11,40 +11,40 @@ public class LoginResponsePacket : IPacket
public void Deserialize(byte[] data)
{
LoginResponseReason = (LoginResponseReason)data[0];
UnknownFlag = data[1];
IsGameMaster = BitConverter.ToBoolean(data, 2);
this.LoginResponseReason = (LoginResponseReason)data[0];
this.UnknownFlag = data[1];
this.IsGameMaster = BitConverter.ToBoolean(data, 2);
var channelAmount = BitConverter.ToUInt16(data, 3);
var sizeOfServerChannelData = 5;
ChannelData = Enumerable.Repeat(0, channelAmount).Select(i => new ServerChannelData
this.ChannelData = Enumerable.Repeat(0, channelAmount).Select(i => new ServerChannelData
{
ServerId = BitConverter.ToUInt16(data, 5 + 0 + i * sizeOfServerChannelData),
ChannelId = BitConverter.ToUInt16(data, 5 + 2 + i * sizeOfServerChannelData),
LoadPercentage = data[5 + 4 + i * sizeOfServerChannelData]
ServerId = BitConverter.ToUInt16(data, 5 + 0 + (i * sizeOfServerChannelData)),
ChannelId = BitConverter.ToUInt16(data, 5 + 2 + (i * sizeOfServerChannelData)),
LoadPercentage = data[5 + 4 + (i * sizeOfServerChannelData)]
}).ToArray();
}
public byte[] Serialize()
{
var sizeOfServerChannelData = 5;
Span<byte> dataSpan = stackalloc byte[5 + ChannelData.Length * sizeOfServerChannelData];
Span<byte> dataSpan = stackalloc byte[5 + (this.ChannelData.Length * sizeOfServerChannelData)];
dataSpan.Clear();
dataSpan[0] = (byte)LoginResponseReason;
dataSpan[1] = UnknownFlag;
dataSpan[2] = BitConverter.GetBytes(IsGameMaster)[0];
var bytesOfChannelAmount = BitConverter.GetBytes((ushort)ChannelData.Length);
dataSpan[0] = (byte)this.LoginResponseReason;
dataSpan[1] = this.UnknownFlag;
dataSpan[2] = BitConverter.GetBytes(this.IsGameMaster)[0];
var bytesOfChannelAmount = BitConverter.GetBytes((ushort)this.ChannelData.Length);
dataSpan[3] = bytesOfChannelAmount[0];
dataSpan[4] = bytesOfChannelAmount[1];
for (var i = 0; i < ChannelData.Length; i++)
for (var i = 0; i < this.ChannelData.Length; i++)
{
var bytesOfServerId = BitConverter.GetBytes(ChannelData[i].ServerId);
var bytesOfChannelId = BitConverter.GetBytes(ChannelData[i].ChannelId);
dataSpan[5 + 0 + i * sizeOfServerChannelData] = bytesOfServerId[0];
dataSpan[5 + 1 + i * sizeOfServerChannelData] = bytesOfServerId[1];
dataSpan[5 + 2 + i * sizeOfServerChannelData] = bytesOfChannelId[0];
dataSpan[5 + 3 + i * sizeOfServerChannelData] = bytesOfChannelId[1];
dataSpan[5 + 4 + i * sizeOfServerChannelData] = ChannelData[i].LoadPercentage;
var bytesOfServerId = BitConverter.GetBytes(this.ChannelData[i].ServerId);
var bytesOfChannelId = BitConverter.GetBytes(this.ChannelData[i].ChannelId);
dataSpan[5 + 0 + (i * sizeOfServerChannelData)] = bytesOfServerId[0];
dataSpan[5 + 1 + (i * sizeOfServerChannelData)] = bytesOfServerId[1];
dataSpan[5 + 2 + (i * sizeOfServerChannelData)] = bytesOfChannelId[0];
dataSpan[5 + 3 + (i * sizeOfServerChannelData)] = bytesOfChannelId[1];
dataSpan[5 + 4 + (i * sizeOfServerChannelData)] = this.ChannelData[i].LoadPercentage;
}
return dataSpan.ToArray();

View file

@ -15,5 +15,5 @@ public enum LoginResponseReason : byte
ServerNotFoundOrDBProblem,
LockedDuePayment,
UserDeletedBigpoint,
NoMoreTries,
NoMoreTries
}

View file

@ -1,12 +1,8 @@
namespace Server.Packets;
public class PacketId : Attribute
{
public readonly OperationCode Code;
public PacketId(OperationCode code)
{
Code = code;
}
public PacketId(OperationCode code) => this.Code = code;
}

View file

@ -17,18 +17,18 @@ public class RawPacket
public RawPacket(OperationCode operationCode, byte[] messageBody, uint aliveTime, byte unknownValue2,
byte unknownValue, Guid sessionId, AuthSession session)
{
MessageBody = messageBody;
UnknownValue2 = unknownValue2;
UnknownValue = unknownValue;
SessionId = sessionId;
Session = session;
OperationCode = operationCode;
this.MessageBody = messageBody;
this.UnknownValue2 = unknownValue2;
this.UnknownValue = unknownValue;
this.SessionId = sessionId;
this.Session = session;
this.OperationCode = operationCode;
/*
* 20s = 5
* 15s = 4
* 10s = 3
* client alive time * 5s => uptime
*/
ClientAliveTime = TimeSpan.FromSeconds(5 * aliveTime);
this.ClientAliveTime = TimeSpan.FromSeconds(5 * aliveTime);
}
}

View file

@ -10,7 +10,7 @@ using Server.DB;
using Server.Services;
var builder = Host.CreateApplicationBuilder();
var configurationRoot = builder.Configuration.AddJsonFile("settings.json", optional: false, reloadOnChange: true)
var configurationRoot = builder.Configuration.AddJsonFile("settings.json", false, true)
.AddEnvironmentVariables().Build();
builder.Services.AddLogging();
builder.Logging.AddFile("Logs/Server-{Date}.log", LogLevel.Trace);
@ -34,5 +34,5 @@ builder.Services.AddHostedService<WonderkingAuthServer>(provider => new Wonderki
provider.GetService<ILogger<WonderkingAuthServer>>() ?? throw new InvalidOperationException(),
provider.GetService<IServiceProvider>() ?? throw new InvalidOperationException()));
using IHost host = builder.Build();
using var host = builder.Build();
await host.RunAsync();

View file

@ -21,15 +21,15 @@ public class PacketDistributorService : IHostedService
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
{
_concurrentQueue = new ConcurrentQueue<RawPacket>();
_logger = logger;
_serviceProvider = serviceProvider;
_packetHandlers = new Dictionary<OperationCode, Type>();
_packetsTypes = new Dictionary<OperationCode, Type>();
this._concurrentQueue = new ConcurrentQueue<RawPacket>();
this._logger = logger;
this._serviceProvider = serviceProvider;
this._packetHandlers = new Dictionary<OperationCode, Type>();
this._packetsTypes = new Dictionary<OperationCode, Type>();
var executingAssembly = Assembly.GetExecutingAssembly();
_packetsTypes = GetPacketsWithId(executingAssembly);
_packetHandlers = GetAllPacketHandlersWithId(executingAssembly);
this._packetsTypes = this.GetPacketsWithId(executingAssembly);
this._packetHandlers = this.GetAllPacketHandlersWithId(executingAssembly);
}
private Dictionary<OperationCode, Type> GetPacketsWithId(Assembly executingAssembly)
@ -42,13 +42,13 @@ public class PacketDistributorService : IHostedService
{
packetsWithId.AsParallel().ForAll(packet =>
{
_logger.LogTrace("Packet with ID: {PacketID} has been added as {PacketName}", packet.Key,
this._logger.LogTrace("Packet with ID: {PacketID} has been added as {PacketName}", packet.Key,
packet.Value.FullName);
});
return packetsWithId;
}
_logger.LogCritical("No Packets have been found");
this._logger.LogCritical("No Packets have been found");
throw new IncompleteInitialization();
}
@ -65,34 +65,32 @@ public class PacketDistributorService : IHostedService
{
packetHandlersWithId.AsParallel().ForAll(packetHandler =>
{
_logger.LogTrace("PacketHandler with ID: {PacketID} has been added as {PacketName}", packetHandler.Key,
this._logger.LogTrace("PacketHandler with ID: {PacketID} has been added as {PacketName}",
packetHandler.Key,
packetHandler.Value.FullName);
});
return packetHandlersWithId;
}
_logger.LogCritical("No PacketHandlers have been found");
this._logger.LogCritical("No PacketHandlers have been found");
throw new IncompleteInitialization();
}
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public void AddPacket(RawPacket rawPacket)
{
_concurrentQueue.Enqueue(rawPacket);
Task.Run(() => DequeueRawPacketAsync());
_logger.LogInformation("Packet with ID: {MessageOperationCode} has been received",
this._concurrentQueue.Enqueue(rawPacket);
Task.Run(() => this.DequeueRawPacketAsync());
this._logger.LogInformation("Packet with ID: {MessageOperationCode} has been received",
rawPacket.OperationCode);
}
private async Task DequeueRawPacketAsync()
{
if (_concurrentQueue.TryDequeue(out var item))
if (this._concurrentQueue.TryDequeue(out var item))
{
Task.Run(() => { InvokePacketHandler(item); });
Task.Run(() => { this.InvokePacketHandler(item); });
}
else
{
@ -102,24 +100,21 @@ public class PacketDistributorService : IHostedService
private void InvokePacketHandler(RawPacket? item)
{
_logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} is being dequeued",
this._logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} is being dequeued",
item.Session.Id, item.OperationCode);
var packetType = _packetsTypes[item.OperationCode];
var packetType = this._packetsTypes[item.OperationCode];
var packet = (IPacket)Activator.CreateInstance(packetType)!;
packet.Deserialize(item.MessageBody);
var packetHandler =
ActivatorUtilities.GetServiceOrCreateInstance(_serviceProvider,
_packetHandlers[item.OperationCode]);
ActivatorUtilities.GetServiceOrCreateInstance(this._serviceProvider,
this._packetHandlers[item.OperationCode]);
packetHandler.GetType().GetMethod("HandleAsync")
?.Invoke(packetHandler, new Object[] { packet, item.Session });
_logger.LogDebug("Packet data {PacketData}", JsonConvert.SerializeObject(packet));
_logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} has finished",
?.Invoke(packetHandler, new object[] { packet, item.Session });
this._logger.LogDebug("Packet data {PacketData}", JsonConvert.SerializeObject(packet));
this._logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} has finished",
item.Session.Id,
item.OperationCode);
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

View file

@ -15,51 +15,48 @@ public class WonderkingAuthServer : TcpServer, IHostedService
public WonderkingAuthServer(IPAddress address, int port, ILogger<WonderkingAuthServer> logger,
IServiceProvider serviceProvider) : base(address, port)
{
_logger = logger;
_serviceProvider = serviceProvider;
this._logger = logger;
this._serviceProvider = serviceProvider;
}
protected override TcpSession CreateSession() =>
ActivatorUtilities.CreateInstance<AuthSession>(_serviceProvider,this);
ActivatorUtilities.CreateInstance<AuthSession>(this._serviceProvider, this);
protected override void OnStarting()
{
_logger.LogInformation("Starting");
this._logger.LogInformation("Starting");
base.OnStarting();
}
protected override void OnStarted()
{
_logger.LogInformation("Started");
this._logger.LogInformation("Started");
base.OnStarted();
}
protected override void OnStopping()
{
_logger.LogInformation("Stopping");
this._logger.LogInformation("Stopping");
base.OnStopping();
}
protected override void OnStopped()
{
_logger.LogInformation("Stopped");
this._logger.LogInformation("Stopped");
base.OnStopped();
}
protected override void OnError(SocketError error)
{
_logger.LogError("An error has occured {Error}", error);
}
protected override void OnError(SocketError error) => this._logger.LogError("An error has occured {Error}", error);
public Task StartAsync(CancellationToken cancellationToken)
{
Start();
this.Start();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
Stop();
this.Stop();
return Task.CompletedTask;
}
}