Created
September 4, 2020 21:37
-
-
Save Const-me/0745e09695e8e8615c14b18fc3fbe028 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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