Skip to content

Commit

Permalink
Update to my (@Sparronator9999's) fork of NamedPipeWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Sparronator9999 committed Sep 4, 2024
1 parent 3d9687f commit dc819a6
Show file tree
Hide file tree
Showing 20 changed files with 831 additions and 567 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ details.

This project makes use of the following third-party libraries:

- A modified version of Twosense's fork of [Named Pipe Wrapper](https://github.com/twosense/named-pipe-wrapper)
for communication between the service and UI program (called `YAMDCC.IPC` in the source files).
- My fork of [Named Pipe Wrapper](https://github.com/Sparronator9999/NamedPipeWrapper) for\
communication between the service and UI program (called `YAMDCC.IPC` in the source files).
- [WinRing0](https://github.com/QCute/WinRing0) for low-level hardware access required to
read/write the EC.
6 changes: 3 additions & 3 deletions YAMDCC.GUI/MainWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,12 @@ private void OnProcessExit(object sender, EventArgs e)
IPCClient.Stop();
}

private void IPC_MessageReceived(NamedPipeConnection<ServiceResponse, ServiceCommand> connection, ServiceResponse message)
private void IPC_MessageReceived(object sender, PipeMessageEventArgs<ServiceResponse, ServiceCommand> e)
{
string[] args = message.Value.Split(' ');
string[] args = e.Message.Value.Split(' ');
if (args.Length == 1)
{
switch (message.Response)
switch (e.Message.Response)
{
case Response.Temp:
if (int.TryParse(args[0], out int value))
Expand Down
16 changes: 16 additions & 0 deletions YAMDCC.IPC/ConnectionFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.IO.Pipes;

namespace YAMDCC.IPC
{
internal static class ConnectionFactory
{
private static int _lastId;

internal static NamedPipeConnection<TRead, TWrite> CreateConnection<TRead, TWrite>(PipeStream pipeStream)
where TRead : class
where TWrite : class
{
return new NamedPipeConnection<TRead, TWrite>(++_lastId, $"Client {_lastId}", pipeStream);
}
}
}
105 changes: 45 additions & 60 deletions YAMDCC.IPC/IO/PipeStreamReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,74 @@ namespace YAMDCC.IPC.IO
{
/// <summary>
/// Wraps a <see cref="PipeStream"/> object and reads from it.
/// </summary>
/// <remarks>
/// Deserializes binary data sent by a <see cref="PipeStreamWriter{T}"/>
/// into a .NET CLR object specified by <typeparamref name="T"/>.
/// </summary>
/// </remarks>
/// <typeparam name="T">
/// Reference type to deserialize data to
/// The reference type to deserialize data to.
/// </typeparam>
public class PipeStreamReader<T> where T : class
internal sealed class PipeStreamReader<T> where T : class
{
/// <summary>
/// Gets the underlying <c>PipeStream</c> object.
/// Gets the underlying <see cref="PipeStream"/> object.
/// </summary>
public PipeStream BaseStream { get; private set; }
internal PipeStream BaseStream { get; private set; }

/// <summary>
/// Gets a value indicating whether the pipe is connected or not.
/// </summary>
public bool IsConnected { get; private set; }
internal bool IsConnected { get; private set; }

private readonly BinaryFormatter _binaryFormatter = new BinaryFormatter();

/// <summary>
/// Constructs a new <see cref="PipeStreamReader{T}"/> object that
/// reads data from the given <paramref name="stream"/>.
/// Constructs a new <see cref="PipeStreamReader{T}"/> object
/// that reads data from the given <paramref name="stream"/>.
/// </summary>
/// <param name="stream">Pipe to read from</param>
public PipeStreamReader(PipeStream stream)
/// <param name="stream">
/// The pipe stream to read from.
/// </param>
internal PipeStreamReader(PipeStream stream)
{
BaseStream = stream;
IsConnected = stream.IsConnected;
}

#region Private stream readers

/// <summary>
/// Reads the length of the next message (in bytes) from the client.
/// Reads the next object from the pipe.
/// </summary>
/// <remarks>
/// This method blocks until an object is
/// sent or the pipe is disconnected.
/// </remarks>
/// <returns>
/// Number of bytes of data the client will be sending.
/// The next object read from the pipe, or
/// <c>null</c> if the pipe disconnected.
/// </returns>
/// <exception cref="InvalidOperationException">
/// The pipe is disconnected, waiting to connect,
/// or the handle has not been set.
/// </exception>
/// <exception cref="IOException">
/// Any I/O error occurred.
/// </exception>
/// <exception cref="SerializationException"/>
internal T ReadObject()
{
if (typeof(T) == typeof(string))
{
const int bufferSize = 1024;
byte[] data = new byte[bufferSize];
BaseStream.Read(data, 0, bufferSize);
string message = Encoding.Unicode.GetString(data).TrimEnd('\0');

return (message.Length > 0 ? message : null) as T;
}
int len = ReadLength();
return len == 0 ? default : ReadObject(len);
}

/// <summary>
/// Reads the length of the next message (in bytes) from the client.
/// </summary>
/// <returns>Number of bytes of data the client will be sending.</returns>
/// <exception cref="InvalidOperationException"/>
/// <exception cref="IOException"/>
private int ReadLength()
{
const int lensize = sizeof(int);
Expand All @@ -71,52 +93,15 @@ private int ReadLength()
: IPAddress.NetworkToHostOrder(BitConverter.ToInt32(lenbuf, 0));
}

/// <exception cref="SerializationException">
/// An object in the graph of type parameter
/// <typeparamref name="T"/> is not marked as serializable.
/// </exception>
/// <exception cref="SerializationException"/>
private T ReadObject(int len)
{
byte[] data = new byte[len];
BaseStream.Read(data, 0, len);
using (MemoryStream memoryStream = new MemoryStream(data))
{
return (T) _binaryFormatter.Deserialize(memoryStream);
return (T)_binaryFormatter.Deserialize(memoryStream);
}
}

#endregion

/// <summary>
/// Reads the next object from the pipe. This method blocks until an
/// object is sent or the pipe is disconnected.
/// </summary>
/// <returns>
/// The next object read from the pipe, or
/// <c>null</c> if the pipe disconnected.
/// </returns>
/// <exception cref="SerializationException">
/// An object in the graph of type parameter
/// <typeparamref name="T"/> is not marked as serializable.
/// </exception>
public T ReadObject()
{
if (typeof(T) == typeof(string))
{
return (T) ReadString();
}
int len = ReadLength();
return len == 0 ? default : ReadObject(len);
}

private object ReadString()
{
const int bufferSize = 1024;
byte[] data = new byte[bufferSize];
BaseStream.Read(data, 0, bufferSize);
string message = Encoding.Unicode.GetString(data).TrimEnd('\0');

return message.Length > 0 ? message : null;
}
}
}
124 changes: 71 additions & 53 deletions YAMDCC.IPC/IO/PipeStreamWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,113 +6,124 @@
namespace YAMDCC.IPC.IO
{
/// <summary>
/// Wraps a <see cref="PipeStream"/> object to read and write .NET CLR objects.
/// Wraps a <see cref="PipeStream"/> object
/// to read and write .NET CLR objects.
/// </summary>
/// <typeparam name="TRdWr">
/// Reference type to read from and write to the pipe
/// <typeparam name="TReadWrite">
/// The reference type to read from and write to the pipe.
/// </typeparam>
public class PipeStreamWrapper<TRdWr> : PipeStreamWrapper<TRdWr, TRdWr>
where TRdWr : class
internal sealed class PipeStreamWrapper<TReadWrite> : PipeStreamWrapper<TReadWrite, TReadWrite>
where TReadWrite : class
{
/// <summary>
/// Constructs a new <c>PipeStreamWrapper</c> object that
/// reads from and writes to the given <paramref name="stream"/>.
/// Constructs a new <see cref="PipeStreamWrapper{TReadWrite}"/> object
/// that reads from and writes to the given <paramref name="stream"/>.
/// </summary>
/// <param name="stream">
/// Stream to read from and write to
/// The pipe stream to read from and write to.
/// </param>
public PipeStreamWrapper(PipeStream stream) : base(stream) { }
public PipeStreamWrapper(PipeStream stream)
: base(stream) { }
}

/// <summary>
/// Wraps a <see cref="PipeStream"/> object to read and write .NET CLR objects.
/// Wraps a <see cref="PipeStream"/> object
/// to read and write .NET CLR objects.
/// </summary>
/// <typeparam name="TRd">
/// Reference type to <b>read</b> from the pipe
/// <typeparam name="TRead">
/// The reference type to read from the pipe.
/// </typeparam>
/// <typeparam name="TWr">
/// Reference type to <b>write</b> to the pipe
/// <typeparam name="TWrite">
/// The reference type to write to the pipe.
/// </typeparam>
public class PipeStreamWrapper<TRd, TWr>
where TRd : class
where TWr : class
internal class PipeStreamWrapper<TRead, TWrite>
where TRead : class
where TWrite : class
{
/// <summary>
/// Gets the underlying <c>PipeStream</c> object.
/// Gets the underlying <see cref="PipeStream"/> object.
/// </summary>
public PipeStream BaseStream { get; private set; }
internal PipeStream BaseStream { get; private set; }

/// <summary>
/// Gets a value indicating whether the
/// <see cref="BaseStream"/> object is connected or not.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="BaseStream"/>
/// object is connected; otherwise, <c>false</c>.
/// object is connected, otherwise <c>false</c>.
/// </returns>
public bool IsConnected => BaseStream.IsConnected && _reader.IsConnected;
internal bool IsConnected => BaseStream.IsConnected && _reader.IsConnected;

/// <summary>
/// Gets a value indicating whether the
/// current stream supports read operations.
/// </summary>
/// <returns>
/// <c>true</c> if the stream supports read
/// operations; otherwise, <c>false</c>.
/// operations, otherwise <c>false</c>.
/// </returns>
public bool CanRead => BaseStream.CanRead;
internal bool CanRead => BaseStream.CanRead;

/// <summary>
/// Gets a value indicating whether the
/// current stream supports write operations.
/// Gets a value indicating whether the current
/// stream supports write operations.
/// </summary>
/// <returns>
/// <c>true</c> if the stream supports write
/// operations; otherwise, <c>false</c>.
/// operation, otherwise <c>false</c>.
/// </returns>
public bool CanWrite => BaseStream.CanWrite;
internal bool CanWrite => BaseStream.CanWrite;

private readonly PipeStreamReader<TRd> _reader;
private readonly PipeStreamWriter<TWr> _writer;
private readonly PipeStreamReader<TRead> _reader;
private readonly PipeStreamWriter<TWrite> _writer;

/// <summary>
/// Constructs a new <c>PipeStreamWrapper</c> object that reads
/// from and writes to the given <paramref name="stream"/>.
/// Constructs a new <see cref="PipeStreamWrapper{TRead, TWrite}"/>
/// object that reads from and writes to the given
/// <paramref name="stream"/>.
/// </summary>
/// <param name="stream">Stream to read from and write to</param>
public PipeStreamWrapper(PipeStream stream)
/// <param name="stream">
/// The stream to read from and write to.
/// </param>
internal PipeStreamWrapper(PipeStream stream)
{
BaseStream = stream;
_reader = new PipeStreamReader<TRd>(BaseStream);
_writer = new PipeStreamWriter<TWr>(BaseStream);
_reader = new PipeStreamReader<TRead>(BaseStream);
_writer = new PipeStreamWriter<TWrite>(BaseStream);
}

/// <summary>
/// Reads the next object from the pipe. This method blocks
/// until an object is sent or the pipe is disconnected.
/// Reads the next object from the pipe.
/// </summary>
/// <remarks>
/// This method blocks until an object
/// is sent or the pipe is disconnected.
/// </remarks>
/// <returns>
/// The next object read from the pipe, or
/// <c>null</c> if the pipe disconnected.
/// </returns>
/// <exception cref="SerializationException">
/// An object in the graph of type parameter
/// <typeparamref name="TRd"/> is not marked as serializable.
/// </exception>
public TRd ReadObject() => _reader.ReadObject();
/// <exception cref="SerializationException"/>
internal TRead ReadObject()
{
return _reader.ReadObject();
}

/// <summary>
/// Writes an object to the pipe.
/// This method blocks until all data is sent.
/// </summary>
/// <remarks>
/// This method blocks until all data is sent.
/// </remarks>
/// <param name="obj">
/// Object to write to the pipe
/// Tne object to write to the pipe.
/// </param>
/// <exception cref="SerializationException">
/// An object in the graph of type parameter
/// <typeparamref name="TRd"/> is not marked as serializable.
/// </exception>
public void WriteObject(TWr obj) => _writer.WriteObject(obj);
/// <exception cref="SerializationException"/>
internal void WriteObject(TWrite obj)
{
_writer.WriteObject(obj);
}

/// <summary>
/// Waits for the other end of the pipe to read all sent bytes.
Expand All @@ -126,12 +137,19 @@ public PipeStreamWrapper(PipeStream stream)
/// <exception cref="IOException">
/// The pipe is broken or another I/O error occurred.
/// </exception>
public void WaitForPipeDrain() => _writer.WaitForPipeDrain();
internal void WaitForPipeDrain()
{
_writer.WaitForPipeDrain();
}

/// <summary>
/// Closes the current stream and releases any resources
/// (such as sockets and file handles) associated with the current stream.
/// Closes the current stream and releases any
/// resources (such as sockets and file handles)
/// associated with the current stream.
/// </summary>
public void Close() => BaseStream.Close();
internal void Close()
{
BaseStream.Close();
}
}
}
Loading

0 comments on commit dc819a6

Please sign in to comment.