Skip to content

Commit

Permalink
More Span, More NAWS
Browse files Browse the repository at this point in the history
  • Loading branch information
HarryCordewener committed Jan 8, 2024
1 parent df0512e commit d02335e
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 37 deletions.
24 changes: 12 additions & 12 deletions TelnetNegotiationCore.TestClient/MockPipelineClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
using TelnetNegotiationCore.Interpreters;
using System.IO.Pipelines;
using Pipelines.Sockets.Unofficial;
using System.Buffers;
using System.Text;
using TelnetNegotiationCore.Models;
using System.Net;
using System.Collections.Immutable;

namespace TelnetNegotiationCore.TestClient
Expand All @@ -33,20 +31,23 @@ private async Task WriteToOutputStreamAsync(byte[] arg, PipeWriter writer)
}

public static Task WriteBackAsync(byte[] writeback, Encoding encoding, TelnetInterpreter t) =>
Task.Run(() => Console.WriteLine(encoding.GetString(writeback)));
Task.Run(() => Console.WriteLine(encoding.GetString(writeback.AsSpan())));

public Task SignalGMCPAsync((string module, string writeback) val) =>
Task.Run(() => _Logger.Debug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback));
public Task SignalGMCPAsync((string module, string writeback) val)
{
_Logger.Debug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback);
return Task.CompletedTask;
}

public Task SignalMSSPAsync(MSSPConfig val) =>
Task.Run(() => _Logger.Debug("New MSSP: {@MSSP}", val));
public Task SignalMSSPAsync(MSSPConfig val)
{
_Logger.Debug("New MSSP: {@MSSPConfig}", val);
return Task.CompletedTask;
}

public Task SignalPromptAsync() =>
Task.Run(() => _Logger.Debug("Prompt"));

public Task SignalNAWSAsync(int height, int width) =>
Task.Run(() => _Logger.Debug("Client Height and Width updated: {Height}x{Width}", height, width));

public async Task StartAsync(string address, int port)
{
var client = new TcpClient(address, port);
Expand All @@ -59,7 +60,6 @@ public async Task StartAsync(string address, int port)
CallbackNegotiationAsync = (x) => WriteToOutputStreamAsync(x, pipe.Output),
SignalOnGMCPAsync = SignalGMCPAsync,
SignalOnMSSPAsync = SignalMSSPAsync,
SignalOnNAWSAsync = SignalNAWSAsync,
SignalOnPromptingAsync = SignalPromptAsync,
CharsetOrder = new[] { Encoding.GetEncoding("utf-8"), Encoding.GetEncoding("iso-8859-1") }
}.BuildAsync();
Expand All @@ -68,7 +68,7 @@ public async Task StartAsync(string address, int port)

while (true)
{
var read = Console.ReadLine() + Environment.NewLine;
string read = Console.ReadLine() ?? string.Empty;

if (telnet != null)
{
Expand Down
25 changes: 17 additions & 8 deletions TelnetNegotiationCore.TestServer/KestrelMockServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class KestrelMockServer : ConnectionHandler
{
private readonly ILogger _Logger;

public KestrelMockServer(ILogger logger = null): base()
public KestrelMockServer(ILogger logger = null) : base()
{
Console.OutputEncoding = Encoding.UTF8;
_Logger = logger ?? Log.Logger.ForContext<KestrelMockServer>();
Expand All @@ -34,14 +34,23 @@ private async Task WriteToOutputStreamAsync(byte[] arg, PipeWriter writer)
}
}

public Task SignalGMCPAsync((string module, string writeback) val) =>
Task.Run(() => _Logger.Debug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback));
public Task SignalGMCPAsync((string module, string writeback) val)
{
_Logger.Debug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback);
return Task.CompletedTask;
}

public Task SignalMSSPAsync(MSSPConfig val) =>
Task.Run(() => _Logger.Debug("New MSSP: {@MSSPConfig}", val));
public Task SignalMSSPAsync(MSSPConfig val)
{
_Logger.Debug("New MSSP: {@MSSPConfig}", val);
return Task.CompletedTask;
}

public Task SignalNAWSAsync(int height, int width) =>
Task.Run(() => _Logger.Debug("Client Height and Width updated: {Height}x{Width}", height, width));
public Task SignalNAWSAsync(int height, int width)
{
_Logger.Debug("Client Height and Width updated: {Height}x{Width}", height, width);
return Task.CompletedTask;
}

public static async Task WriteBackAsync(byte[] writeback, Encoding encoding, TelnetInterpreter telnet)
{
Expand All @@ -59,7 +68,7 @@ public async override Task OnConnectedAsync(ConnectionContext connection)

var telnet = await new TelnetInterpreter(TelnetInterpreter.TelnetMode.Server)
{
CallbackOnSubmitAsync = (w,e,t) => WriteBackAsync(w,e,t),
CallbackOnSubmitAsync = (w, e, t) => WriteBackAsync(w, e, t),
SignalOnGMCPAsync = SignalGMCPAsync,
SignalOnMSSPAsync = SignalMSSPAsync,
SignalOnNAWSAsync = SignalNAWSAsync,
Expand Down
22 changes: 12 additions & 10 deletions TelnetNegotiationCore/Interpreters/TelnetEORInterpreter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Stateless;
using TelnetNegotiationCore.Models;
Expand Down Expand Up @@ -119,7 +120,15 @@ private async Task OnWillEORAsync(StateMachine<State, Trigger>.Transition _)
/// <returns>A completed Task</returns>
public async Task SendPromptAsync(byte[] send)
{
await CallbackNegotiationAsync(send);
await CallbackNegotiationAsync(send);
if (_doEOR is null or false)
{
await CallbackNegotiationAsync(CurrentEncoding.GetBytes(Environment.NewLine));
}
else
{
await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.EOR]);
}
}

/// <summary>
Expand All @@ -129,15 +138,8 @@ public async Task SendPromptAsync(byte[] send)
/// <returns>A completed Task</returns>
public async Task SendAsync(byte[] send)
{
if (_doEOR is null or false)
{
await CallbackNegotiationAsync(send);
}
else
{
await CallbackNegotiationAsync(send);
await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.EOR]);
}
await CallbackNegotiationAsync(send);
await CallbackNegotiationAsync(CurrentEncoding.GetBytes(Environment.NewLine));
}
}
}
22 changes: 16 additions & 6 deletions TelnetNegotiationCore/Interpreters/TelnetNAWSInterpreter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using OneOf;
using Stateless;
Expand Down Expand Up @@ -48,7 +49,7 @@ public partial class TelnetInterpreter
/// <summary>
/// This exists to avoid an infinite loop with badly conforming clients.
/// </summary>
private bool _ClientWillingToDoNAWS = false;
private bool _WillingToDoNAWS = false;

/// <summary>
/// If the server you are connected to makes use of the client window in ways that are linked to its width and height,
Expand Down Expand Up @@ -90,8 +91,8 @@ private StateMachine<State, Trigger> SetupNAWS(StateMachine<State, Trigger> tsm)
.OnEntry(() => _Logger.Debug("Connection: {ConnectionState}", "Server won't do NAWS - do nothing"));

tsm.Configure(State.DoNAWS)
.SubstateOf(State.Accepting);
// Fix this. We are a client.
.SubstateOf(State.Accepting)
.OnEntry(() => _WillingToDoNAWS = true);
}

tsm.Configure(State.WillDoNAWS)
Expand All @@ -100,7 +101,7 @@ private StateMachine<State, Trigger> SetupNAWS(StateMachine<State, Trigger> tsm)

tsm.Configure(State.WontDoNAWS)
.SubstateOf(State.Accepting)
.OnEntry(() => _ClientWillingToDoNAWS = false);
.OnEntry(() => _WillingToDoNAWS = false);

tsm.Configure(State.SubNegotiation)
.Permit(Trigger.NAWS, State.NegotiatingNAWS);
Expand Down Expand Up @@ -130,17 +131,26 @@ private StateMachine<State, Trigger> SetupNAWS(StateMachine<State, Trigger> tsm)
return tsm;
}

public async Task SendNAWS(short width, short height)
{
if(!_WillingToDoNAWS) await Task.CompletedTask;

await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.SB, (byte)Trigger.NAWS,
.. BitConverter.GetBytes(width), .. BitConverter.GetBytes(height),
(byte)Trigger.IAC, (byte)Trigger.SE]);
}

/// <summary>
/// Request NAWS from a client
/// </summary>
public async Task RequestNAWSAsync(StateMachine<State, Trigger>.Transition _)
{
if (!_ClientWillingToDoNAWS)
if (!_WillingToDoNAWS)
{
_Logger.Debug("Connection: {ConnectionState}", "Requesting NAWS details from Client");

await CallbackNegotiationAsync([(byte)Trigger.IAC, (byte)Trigger.DO, (byte)Trigger.NAWS]);
_ClientWillingToDoNAWS = true;
_WillingToDoNAWS = true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ private async Task WriteToBufferAndAdvanceAsync(OneOf<byte, Trigger> b)
private void WriteToOutput()
{
byte[] cp = new byte[_bufferPosition];
Array.Copy(_buffer, cp, _bufferPosition);
_buffer.AsSpan().CopyTo(cp);
_bufferPosition = 0;
CallbackOnSubmitAsync.Invoke(cp, CurrentEncoding, this);
}
Expand Down

0 comments on commit d02335e

Please sign in to comment.