-
Notifications
You must be signed in to change notification settings - Fork 0
/
MockPipelineClient.cs
96 lines (82 loc) · 2.76 KB
/
MockPipelineClient.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System.Net.Sockets;
using TelnetNegotiationCore.Interpreters;
using System.IO.Pipelines;
using Pipelines.Sockets.Unofficial;
using System.Text;
using TelnetNegotiationCore.Models;
using System.Collections.Immutable;
using Microsoft.Extensions.Logging;
namespace TelnetNegotiationCore.TestClient
{
public class MockPipelineClient(ILogger<MockPipelineClient> logger)
{
private async Task WriteToOutputStreamAsync(byte[] arg, PipeWriter writer)
{
try
{
await writer.WriteAsync(new ReadOnlyMemory<byte>(arg), CancellationToken.None);
}
catch (ObjectDisposedException ode)
{
logger.LogError(ode, "Stream has been closed");
}
}
public static Task WriteBackAsync(byte[] writeback, Encoding encoding, TelnetInterpreter t) =>
Task.Run(() => Console.WriteLine(encoding.GetString(writeback.AsSpan())));
public Task SignalGMCPAsync((string module, string writeback) val)
{
logger.LogDebug("GMCP Signal: {Module}: {WriteBack}", val.module, val.writeback);
return Task.CompletedTask;
}
public Task SignalMSSPAsync(MSSPConfig val)
{
logger.LogDebug("New MSSP: {@MSSPConfig}", val);
return Task.CompletedTask;
}
public Task SignalPromptAsync() =>
Task.Run(() => logger.LogDebug("Prompt"));
public async Task StartAsync(string address, int port)
{
var client = new TcpClient(address, port);
var stream = client.GetStream();
var pipe = StreamConnection.GetDuplex(stream, new PipeOptions());
var telnet = await new TelnetInterpreter(TelnetInterpreter.TelnetMode.Client, logger)
{
CallbackOnSubmitAsync = WriteBackAsync,
CallbackNegotiationAsync = (x) => WriteToOutputStreamAsync(x, pipe.Output),
SignalOnGMCPAsync = SignalGMCPAsync,
SignalOnMSSPAsync = SignalMSSPAsync,
SignalOnPromptingAsync = SignalPromptAsync,
CharsetOrder = new[] { Encoding.GetEncoding("utf-8"), Encoding.GetEncoding("iso-8859-1") }
}.BuildAsync();
var backgroundTask = Task.Run(() => ReadFromPipeline(telnet, pipe.Input));
while (true)
{
string read = Console.ReadLine() ?? string.Empty;
if (telnet != null)
{
await telnet.SendPromptAsync(telnet?.CurrentEncoding.GetBytes(read));
}
}
}
/// <summary>
/// Read data coming from the server and interpret it.
/// </summary>
/// <param name="reader">The Pipeline Reader</param>
/// <returns>A ValueTask</returns>
static async ValueTask ReadFromPipeline(TelnetInterpreter telnet, PipeReader reader)
{
while (true)
{
// await some data being available
ReadResult read = await reader.ReadAtLeastAsync(1);
foreach(var segment in read.Buffer)
{
await telnet.InterpretByteArrayAsync(segment.Span.ToImmutableArray());
}
// tell the pipe that we used everything
reader.AdvanceTo(read.Buffer.End);
}
}
}
}