From e08bc60dd00dc2ac5c2ac5559a43ab6f84196df8 Mon Sep 17 00:00:00 2001 From: Harry Cordewener Date: Wed, 3 Jan 2024 20:20:25 -0600 Subject: [PATCH] Target .Net 8.0 --- .github/workflows/dotnet.yml | 2 +- .../MockPipelineClient.cs | 2 +- .../KestrelMockServer.cs | 8 +++-- TelnetNegotiationCore.TestServer/Startup.cs | 12 ++----- .../CHARSETTests.cs | 14 ++------ .../CreateDotGraph.cs | 2 +- TelnetNegotiationCore.UnitTests/TTypeTests.cs | 11 ++----- .../TelnetNegotiationCore.UnitTests.csproj | 2 +- .../Interpreters/TelnetCharsetInterpreter.cs | 28 ++++++++-------- .../Interpreters/TelnetGMCPInterpreter.cs | 32 ++++++++++--------- .../Interpreters/TelnetStandardInterpreter.cs | 20 ++++++------ .../TelnetNegotiationCore.csproj | 2 +- 12 files changed, 58 insertions(+), 77 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 46b5b4c..027bfca 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,7 +16,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v2 with: - dotnet-version: 6.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/TelnetNegotiationCore.TestClient/MockPipelineClient.cs b/TelnetNegotiationCore.TestClient/MockPipelineClient.cs index 8c235ae..04e9402 100644 --- a/TelnetNegotiationCore.TestClient/MockPipelineClient.cs +++ b/TelnetNegotiationCore.TestClient/MockPipelineClient.cs @@ -35,7 +35,7 @@ private async Task WriteToOutputStreamAsync(byte[] arg, PipeWriter writer) public static Task WriteBackAsync(byte[] writeback, Encoding encoding) => Task.Run(() => Console.WriteLine(encoding.GetString(writeback))); - public Task SignalGMCPAsync((string module, string writeback) val, Encoding encoding) => + public Task SignalGMCPAsync((string module, string writeback) val) => Task.Run(() => _Logger.Debug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback)); public Task SignalMSSPAsync(MSSPConfig val) => diff --git a/TelnetNegotiationCore.TestServer/KestrelMockServer.cs b/TelnetNegotiationCore.TestServer/KestrelMockServer.cs index 21515db..d5446a4 100644 --- a/TelnetNegotiationCore.TestServer/KestrelMockServer.cs +++ b/TelnetNegotiationCore.TestServer/KestrelMockServer.cs @@ -15,6 +15,8 @@ namespace TelnetNegotiationCore.TestServer public class KestrelMockServer : ConnectionHandler { readonly ILogger _Logger; + private static readonly string[] config = ["ABC", "DEF"]; + private static readonly string[] value = ["Moo", "Meow"]; public KestrelMockServer(ILogger logger = null): base() { @@ -34,7 +36,7 @@ private async Task WriteToOutputStreamAsync(byte[] arg, PipeWriter writer) } } - public Task SignalGMCPAsync((string module, string writeback) val, Encoding encoding) => + public Task SignalGMCPAsync((string module, string writeback) val) => Task.Run(() => _Logger.Debug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback)); public Task SignalMSSPAsync(MSSPConfig val) => @@ -63,11 +65,11 @@ public async override Task OnConnectedAsync(ConnectionContext connection) { Name = "My Telnet Negotiated Server", UTF_8 = true, - Gameplay = new[] { "ABC", "DEF" }, + Gameplay = config, Extended = new Dictionary { { "Foo", "Bar"}, - { "Baz", new [] {"Moo", "Meow" }} + { "Baz", value } } }) .BuildAsync(); diff --git a/TelnetNegotiationCore.TestServer/Startup.cs b/TelnetNegotiationCore.TestServer/Startup.cs index f55538c..6d8ae02 100644 --- a/TelnetNegotiationCore.TestServer/Startup.cs +++ b/TelnetNegotiationCore.TestServer/Startup.cs @@ -9,17 +9,9 @@ public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 - public void ConfigureServices(IServiceCollection services) - { - } + public static void ConfigureServices(IServiceCollection _) { } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - app.Run(async (context) => - { - await Task.CompletedTask; - }); - } + public static void Configure(IApplicationBuilder app, IHostingEnvironment _) => app.Run(async _ => await Task.CompletedTask); } } diff --git a/TelnetNegotiationCore.UnitTests/CHARSETTests.cs b/TelnetNegotiationCore.UnitTests/CHARSETTests.cs index 57e00d5..8a42f4c 100644 --- a/TelnetNegotiationCore.UnitTests/CHARSETTests.cs +++ b/TelnetNegotiationCore.UnitTests/CHARSETTests.cs @@ -17,19 +17,11 @@ public class CHARSETTests private Task WriteBackToOutput(byte[] arg1, Encoding arg2) => throw new NotImplementedException(); - private Task WriteBackToGMCP((string module, string writeback) arg1, Encoding arg2) => throw new NotImplementedException(); + private Task WriteBackToGMCP((string module, string writeback) arg1) => throw new NotImplementedException(); - private Task ClientWriteBackToNegotiate(byte[] arg1) - { - _negotiationOutput = arg1; - return Task.CompletedTask; - } + private Task ClientWriteBackToNegotiate(byte[] arg1) => Task.Run(() => _negotiationOutput = arg1); - private Task ServerWriteBackToNegotiate(byte[] arg1) - { - _negotiationOutput = arg1; - return Task.CompletedTask; - } + private Task ServerWriteBackToNegotiate(byte[] arg1) => Task.Run(() => _negotiationOutput = arg1); [SetUp] public void Setup() diff --git a/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs b/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs index 9ff5b40..49b4f56 100644 --- a/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs +++ b/TelnetNegotiationCore.UnitTests/CreateDotGraph.cs @@ -71,6 +71,6 @@ public async Task WriteServerDotGraph() private async Task WriteBack(byte[] arg1, Encoding encoding) => await Task.CompletedTask; - private async Task WriteBackToGMCP((string module, string writeback) arg1, Encoding arg2) => await Task.CompletedTask; + private async Task WriteBackToGMCP((string module, string writeback) arg1) => await Task.CompletedTask; } } diff --git a/TelnetNegotiationCore.UnitTests/TTypeTests.cs b/TelnetNegotiationCore.UnitTests/TTypeTests.cs index d2d4adb..55e8011 100644 --- a/TelnetNegotiationCore.UnitTests/TTypeTests.cs +++ b/TelnetNegotiationCore.UnitTests/TTypeTests.cs @@ -20,16 +20,9 @@ public class TTypeTests private Task WriteBackToOutput(byte[] arg1, Encoding arg2) => throw new NotImplementedException(); - private Task WriteBackToNegotiate(byte[] arg1) - { - _negotiationOutput = arg1; - return Task.CompletedTask; - } + private Task WriteBackToNegotiate(byte[] arg1) => Task.Run(() => _negotiationOutput = arg1); - private Task WriteBackToGMCP((string Package, string Info) tuple, Encoding encoding) - { - throw new NotImplementedException(); - } + private Task WriteBackToGMCP((string Package, string Info) tuple) => throw new NotImplementedException(); [SetUp] public async Task Setup() diff --git a/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj b/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj index 6290256..74e1576 100644 --- a/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj +++ b/TelnetNegotiationCore.UnitTests/TelnetNegotiationCore.UnitTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false diff --git a/TelnetNegotiationCore/Interpreters/TelnetCharsetInterpreter.cs b/TelnetNegotiationCore/Interpreters/TelnetCharsetInterpreter.cs index c8560f3..8e4340e 100644 --- a/TelnetNegotiationCore/Interpreters/TelnetCharsetInterpreter.cs +++ b/TelnetNegotiationCore/Interpreters/TelnetCharsetInterpreter.cs @@ -153,7 +153,7 @@ private StateMachine SetupCharsetNegotiation(StateMachineIgnored private void GetCharset(StateMachine.Transition _) { - _charsetByteState = new byte[buffer.Length]; + _charsetByteState = new byte[_buffer.Length]; _charsetByteIndex = 0; } @@ -196,7 +196,7 @@ private async Task CompleteCharsetAsync(StateMachine.Transition { if (charsetOffered && Mode == TelnetMode.Server) { - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE]); return; } @@ -212,22 +212,22 @@ private async Task CompleteCharsetAsync(StateMachine.Transition if (chosenEncoding == null) { - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE]); return; } _Logger.Debug("Charsets chosen by us: {@charsetWebName} (CP: {@cp})", chosenEncoding.WebName, chosenEncoding.CodePage); - var preamble = new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.ACCEPTED }; - var charsetAscii = ascii.GetBytes(chosenEncoding.WebName); - var postamble = new byte[] { (byte)Trigger.IAC, (byte)Trigger.SE }; + byte[] preamble = [(byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.ACCEPTED]; + byte[] charsetAscii = ascii.GetBytes(chosenEncoding.WebName); + byte[] postAmble = [ (byte)Trigger.IAC, (byte)Trigger.SE ]; CurrentEncoding = chosenEncoding; // TODO: The implementing Server or Client needs to be warned when CurrentEncoding is set! // This would allow, for instance, the Console to ensure it displays Unicode correctly. - await CallbackNegotiationAsync(preamble.Concat(charsetAscii).Concat(postamble).ToArray()); + await CallbackNegotiationAsync([.. preamble, .. charsetAscii, .. postAmble]); } /// @@ -243,7 +243,7 @@ private async Task CompleteAcceptedCharsetAsync(StateMachine.Tra catch (Exception ex) { _Logger.Error(ex, "Unexpected error during Accepting Charset Negotiation. Could not find charset: {charset}", ascii.GetString(_acceptedCharsetByteState, 0, _acceptedCharsetByteIndex)); - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REJECTED, (byte)Trigger.IAC, (byte)Trigger.SE]); } _Logger.Information("Connection: Accepted Charset Negotiation for: {charset}", CurrentEncoding.WebName); charsetOffered = false; @@ -255,7 +255,7 @@ private async Task CompleteAcceptedCharsetAsync(StateMachine.Tra private async Task OnWillingCharsetAsync(StateMachine.Transition _) { _Logger.Debug("Connection: {ConnectionState}", "Request charset negotiation from Client"); - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.DO, (byte)Trigger.CHARSET }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.DO, (byte)Trigger.CHARSET]); charsetOffered = false; } @@ -265,7 +265,7 @@ private async Task OnWillingCharsetAsync(StateMachine.Transition private async Task WillingCharsetAsync() { _Logger.Debug("Connection: {ConnectionState}", "Announcing willingness to Charset!"); - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.WILL, (byte)Trigger.CHARSET }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.WILL, (byte)Trigger.CHARSET]); } /// @@ -273,7 +273,7 @@ private async Task WillingCharsetAsync() /// private async Task OnDoCharsetAsync(StateMachine.Transition _) { - _Logger.Debug("Charsets String: {charsetlist}", ";" + string.Join(";", _charsetOrder(Encoding.GetEncodings()).Select(x => x.WebName))); + _Logger.Debug("Charsets String: {CharsetList}", ";" + string.Join(";", _charsetOrder(Encoding.GetEncodings()).Select(x => x.WebName))); await CallbackNegotiationAsync(SupportedCharacterSets.Value); charsetOffered = true; } @@ -284,10 +284,10 @@ private async Task OnDoCharsetAsync(StateMachine.Transition _) /// A byte array representing the charset offering. private byte[] CharacterSets() { - byte[] pre = new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REQUEST }; - byte[] post = new byte[] { (byte)Trigger.IAC, (byte)Trigger.SE }; + byte[] pre = [(byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.CHARSET, (byte)Trigger.REQUEST]; + byte[] post = [(byte)Trigger.IAC, (byte)Trigger.SE]; byte[] defaultCharsets = ascii.GetBytes($";{string.Join(";", _charsetOrder(Encoding.GetEncodings()).Select(x => x.WebName))}"); - return pre.Concat(defaultCharsets).Concat(post).ToArray(); + return [.. pre, .. defaultCharsets, .. post]; } } } diff --git a/TelnetNegotiationCore/Interpreters/TelnetGMCPInterpreter.cs b/TelnetNegotiationCore/Interpreters/TelnetGMCPInterpreter.cs index e71c457..b41fcde 100644 --- a/TelnetNegotiationCore/Interpreters/TelnetGMCPInterpreter.cs +++ b/TelnetNegotiationCore/Interpreters/TelnetGMCPInterpreter.cs @@ -12,9 +12,9 @@ namespace TelnetNegotiationCore.Interpreters { public partial class TelnetInterpreter { - private List _gmcpBytes = new(); + private List _GMCPBytes = []; - public Func<(string Package, string Info), Encoding, Task> SignalOnGMCPAsync { get; init; } + public Func<(string Package, string Info), Task> SignalOnGMCPAsync { get; init; } private StateMachine SetupGMCPNegotiation(StateMachine tsm) { @@ -55,7 +55,7 @@ private StateMachine SetupGMCPNegotiation(StateMachine _gmcpBytes.Clear()); + .OnEntry(() => _GMCPBytes.Clear()); TriggerHelper.ForAllTriggersButIAC(t => tsm .Configure(State.EvaluatingGMCPValue) @@ -89,7 +89,7 @@ private StateMachine SetupGMCPNegotiation(StateMachineByte. private void RegisterGMCPValue(OneOf b) { - _gmcpBytes.Add(b.AsT0); + _GMCPBytes.Add(b.AsT0); } public Task SendGMCPCommand(string package, string command) => @@ -101,11 +101,13 @@ public Task SendGMCPCommand(string package, byte[] command) => public async Task SendGMCPCommand(byte[] package, byte[] command) { await CallbackNegotiationAsync( - new byte[] { (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.GMCP } - .Concat(package) - .Concat(CurrentEncoding.GetBytes(" ")) - .Concat(command) - .Concat(new byte[] { (byte)Trigger.IAC, (byte)Trigger.SE }).ToArray()); + [ + (byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.GMCP, + .. package, + .. CurrentEncoding.GetBytes(" "), + .. command, + .. new byte[] { (byte)Trigger.IAC, (byte)Trigger.SE }, + ]); } /// @@ -116,12 +118,12 @@ await CallbackNegotiationAsync( private async Task CompleteGMCPNegotiation(StateMachine.Transition _) { var space = CurrentEncoding.GetBytes(" ").First(); - var firstSpace = _gmcpBytes.FindIndex(x => x == space); - var packageBytes = _gmcpBytes.Take(firstSpace).ToArray(); - var rest = _gmcpBytes.Skip(firstSpace + 1).ToArray(); + var firstSpace = _GMCPBytes.FindIndex(x => x == space); + var packageBytes = _GMCPBytes.Take(firstSpace).ToArray(); + var rest = _GMCPBytes.Skip(firstSpace + 1).ToArray(); // TODO: Check for MSDP information, if so, convert to JSON first, then send as Info. // TODO: Consideration: a version of this that sends back a Dynamic or other similar object. - await (SignalOnGMCPAsync?.Invoke((Package: CurrentEncoding.GetString(packageBytes), Info: CurrentEncoding.GetString(packageBytes)), CurrentEncoding) ?? Task.CompletedTask); + await (SignalOnGMCPAsync?.Invoke((Package: CurrentEncoding.GetString(packageBytes), Info: CurrentEncoding.GetString(packageBytes))) ?? Task.CompletedTask); } /// @@ -133,14 +135,14 @@ private async Task WillGMCPAsync(StateMachine.Transition _) { _Logger.Debug("Connection: {ConnectionState}", "Announcing the server will GMCP"); - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.WILL, (byte)Trigger.GMCP }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.WILL, (byte)Trigger.GMCP]); } private async Task DoGMCPAsync(StateMachine.Transition _) { _Logger.Debug("Connection: {ConnectionState}", "Announcing the client can do GMCP"); - await CallbackNegotiationAsync(new byte[] { (byte)Trigger.IAC, (byte)Trigger.DO, (byte)Trigger.GMCP }); + await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.DO, (byte)Trigger.GMCP]); } } } diff --git a/TelnetNegotiationCore/Interpreters/TelnetStandardInterpreter.cs b/TelnetNegotiationCore/Interpreters/TelnetStandardInterpreter.cs index 4c6c97d..e1ef7a3 100644 --- a/TelnetNegotiationCore/Interpreters/TelnetStandardInterpreter.cs +++ b/TelnetNegotiationCore/Interpreters/TelnetStandardInterpreter.cs @@ -40,12 +40,12 @@ public partial class TelnetInterpreter /// /// Local buffer. We only take up to 5mb in buffer space. /// - private readonly byte[] buffer = new byte[5242880]; + private readonly byte[] _buffer = new byte[5242880]; /// /// Buffer position where we are writing. /// - private int bufferposition = 0; + private int _bufferPosition = 0; /// /// Helper function for Byte parameterized triggers. @@ -95,7 +95,7 @@ public TelnetInterpreter(TelnetMode mode, ILogger logger = null) { Mode = mode; _Logger = logger ?? Log.Logger.ForContext().ForContext("TelnetMode", mode); - _InitialCall = new List>(); + _InitialCall = []; TelnetStateMachine = new StateMachine(State.Accepting); _parameterizedTriggers = new ParameterizedTriggers(); @@ -197,8 +197,8 @@ private async Task WriteToBufferAndAdvanceAsync(OneOf b) { if (b.AsT0 == (byte)Trigger.CARRIAGERETURN) return; _Logger.Verbose("Debug: Writing into buffer: {Byte}", b.AsT0); - buffer[bufferposition] = b.AsT0; - bufferposition++; + _buffer[_bufferPosition] = b.AsT0; + _bufferPosition++; await (CallbackOnByteAsync?.Invoke(b.AsT0, CurrentEncoding) ?? Task.CompletedTask); } @@ -207,9 +207,9 @@ private async Task WriteToBufferAndAdvanceAsync(OneOf b) /// private void WriteToOutput() { - byte[] cp = new byte[bufferposition]; - Array.Copy(buffer, cp, bufferposition); - bufferposition = 0; + byte[] cp = new byte[_bufferPosition]; + Array.Copy(_buffer, cp, _bufferPosition); + _bufferPosition = 0; CallbackOnSubmitAsync.Invoke(cp, CurrentEncoding); } @@ -244,7 +244,7 @@ private void RegisterInitialWilling(Func fun) /// TODO: Cache the value of IsDefined, or get a way to compile this down to a faster call that doesn't require reflection each time. /// /// An integer representation of a byte. - /// Awaitable Task + /// Task public async Task InterpretAsync(byte bt) { if (Enum.IsDefined(typeof(Trigger), (short)bt)) @@ -263,7 +263,7 @@ public async Task InterpretAsync(byte bt) /// TODO: Cache the value of IsDefined, or get a way to compile this down to a faster call that doesn't require reflection each time. /// /// An integer representation of a byte. - /// Awaitable Task + /// Task public async Task InterpretByteArrayAsync(ImmutableArray byteArray) { foreach (var b in byteArray) diff --git a/TelnetNegotiationCore/TelnetNegotiationCore.csproj b/TelnetNegotiationCore/TelnetNegotiationCore.csproj index 6e30216..791a04a 100644 --- a/TelnetNegotiationCore/TelnetNegotiationCore.csproj +++ b/TelnetNegotiationCore/TelnetNegotiationCore.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 latest 1.0.0 True