80 lines
1.9 KiB
C#
80 lines
1.9 KiB
C#
|
using CliWrap;
|
||
|
using InnovEnergy.Lib.Utils;
|
||
|
|
||
|
namespace InnovEnergy.Lib.Channels.V2;
|
||
|
|
||
|
public class CommandChannel : IChannel<IReadOnlyList<Byte>>
|
||
|
{
|
||
|
private UInt32 _BufferSize;
|
||
|
private Command Command { get; }
|
||
|
|
||
|
private readonly MemoryStream _StdIn = new MemoryStream();
|
||
|
private readonly MemoryStream _StdOut = new MemoryStream();
|
||
|
|
||
|
private CommandTask<CommandResult>? _CommandTask;
|
||
|
|
||
|
public CommandChannel(Command command, UInt32 bufferSize = 64)
|
||
|
{
|
||
|
_BufferSize = bufferSize;
|
||
|
|
||
|
Command = command
|
||
|
.WithStandardInputPipe(PipeSource.FromStream(_StdIn))
|
||
|
.WithStandardOutputPipe(PipeTarget.ToStream(_StdOut, true));
|
||
|
}
|
||
|
|
||
|
private void Open()
|
||
|
{
|
||
|
if (_CommandTask is null || _CommandTask.Task.IsCompleted)
|
||
|
{
|
||
|
Close();
|
||
|
_CommandTask = Command.ExecuteAsync(); // TODO: support cancellation
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Close()
|
||
|
{
|
||
|
_StdIn.Seek(0, SeekOrigin.Begin);
|
||
|
_StdOut.Seek(0, SeekOrigin.Begin);
|
||
|
|
||
|
_CommandTask?.Dispose();
|
||
|
_CommandTask = null;
|
||
|
}
|
||
|
|
||
|
|
||
|
public async Task<IReadOnlyList<Byte>> Read()
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
Open();
|
||
|
|
||
|
var buffer = new Byte[_BufferSize];
|
||
|
var nRead = await _StdOut.ReadAsync(buffer, 0, buffer.Length);
|
||
|
|
||
|
if (nRead >= buffer.Length)
|
||
|
_BufferSize *= 2;
|
||
|
else if (nRead <= 0)
|
||
|
throw new IOException("Broken pipe (StdOut)");
|
||
|
|
||
|
return new ArraySegment<Byte>(buffer, 0, nRead);
|
||
|
}
|
||
|
catch
|
||
|
{
|
||
|
Close();
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public async Task Write(IReadOnlyList<Byte> tx)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
Open();
|
||
|
await _StdIn.WriteAsync(tx as Byte[] ?? tx.ToArray(), 0, tx.Count);
|
||
|
}
|
||
|
catch
|
||
|
{
|
||
|
Close();
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
}
|