Skip to content

Instantly share code, notes, and snippets.

@Const-me
Created September 4, 2020 21:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Const-me/0745e09695e8e8615c14b18fc3fbe028 to your computer and use it in GitHub Desktop.
Save Const-me/0745e09695e8e8615c14b18fc3fbe028 to your computer and use it in GitHub Desktop.
using System;
using System.Net;
/// <summary>Readonly stream of bytes</summary>
interface iReadStream
{
/// <summary>Read bytes from the stream.</summary>
/// <remarks>Blocks indefinitely until the entire buffer is filled, throws exceptions when things fail.</remarks>
void read( Span<byte> buffer );
}
static class Factories
{
/// <summary>Open a TCP connection to remote host, return object to read bytes from that socket</summary>
/// <remarks>The state of the stream is the TCP socket</remarks>
public static iReadStream connect( IPEndPoint address )
{
// TODO: write a class that wraps TcpClient from standard library
throw new NotImplementedException();
}
/// <summary>Create a stream that decrypts data from another stream on the fly, with the specified symmetric key</summary>
/// <remarks>The mutable state of the stream is the source stream being wrapped, plus state of AES stream cypher, plus up to 16 bytes of the data (size of AES block)</remarks>
public static iReadStream decrypt( iReadStream encrypted, ReadOnlySpan<byte> key )
{
// TODO: write a class that wraps AesManaged from standard library
throw new NotImplementedException();
}
/// <summary>Create a stream that decompresses GZip from another stream on the fly</summary>
/// <remarks>The mutable state of the stream is the source stream, plus GZip decompressor state</remarks>
public static iReadStream decompressGzip( iReadStream compressed )
{
// TODO: write a class that wraps GZipStream from standard library
throw new NotImplementedException();
}
/// <summary>Create a stream that decompresses LZ4 from another stream on the fly</summary>
/// <remarks>The mutable state of the stream is the source stream, plus LZ4 decompressor state</remarks>
public static iReadStream decompressLz4( iReadStream compressed )
{
// TODO: write a class that uses [DllImport] to call lz4.dll on Windows, or liblz4.so.1 on Linux: https://packages.debian.org/buster/liblz4-1
throw new NotImplementedException();
}
}
enum eCompression: byte
{
None,
GZip,
LZ4,
}
static class Connect
{
public static iReadStream setupConnection( IPEndPoint address, byte[] decryptionKey, eCompression compression )
{
// Here the magic happens: building protocol stack in runtime, based on the arguments.
iReadStream sess = Factories.connect( address );
if( null != decryptionKey )
{
// Encryption was configured, wrap socket into the decryptor
sess = Factories.decrypt( sess, decryptionKey );
}
// Optionally, wrap the session into decompressor
switch( compression )
{
case eCompression.None:
return sess;
case eCompression.GZip:
return Factories.decompressGzip( sess );
case eCompression.LZ4:
return Factories.decompressLz4( sess );
default:
throw new ArgumentException( $"Invalid compression algorithm { compression }" );
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment