Innovenergy_trunk/csharp/lib/Channels/V2/CommandChannel.cs

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;
}
}
}