Skip to content
This repository has been archived by the owner on May 17, 2024. It is now read-only.

Commit

Permalink
Merge pull request #35 from justcoding121/beta
Browse files Browse the repository at this point in the history
Stable
  • Loading branch information
justcoding121 authored May 15, 2018
2 parents 39fa1cc + 65d7cf9 commit ec04103
Show file tree
Hide file tree
Showing 38 changed files with 3,476 additions and 535 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ Supports
### Server Name Indication

```csharp
var yourClientStream = new CustomBufferedStream(clientStream, 4096)
var clientSslHelloInfo = await SslTools.PeekClientHello(yourClientStream);
var bufferPool = new DefaultBufferPool();
var yourClientStream = new CustomBufferedStream(clientStream, bufferPool, 4096)
var clientSslHelloInfo = await SslTools.PeekClientHello(yourClientStream, bufferPool);

//will be null if no client hello was received (not a SSL connection)
if (clientSslHelloInfo != null)
Expand All @@ -44,9 +45,9 @@ if (clientSslHelloInfo != null)

### Peek Client SSL Hello
```csharp

var yourClientStream = new CustomBufferedStream(clientStream, 4096)
var clientSslHelloInfo = await SslTools.PeekClientHello(yourClientStream);
var bufferPool = new DefaultBufferPool();
var yourClientStream = new CustomBufferedStream(clientStream, bufferPool, 4096)
var clientSslHelloInfo = await SslTools.PeekClientHello(yourClientStream, bufferPool);

//will be null if no client hello was received (not a SSL connection)
if(clientSslHelloInfo!=null)
Expand All @@ -59,8 +60,9 @@ if(clientSslHelloInfo!=null)

### Peek Server SSL Hello
```csharp
var yourServerStream = new CustomBufferedStream(serverStream, 4096)
var serverSslHelloInfo = await SslTools.PeekServerHello(yourServerStream);
var bufferPool = new DefaultBufferPool();
var yourServerStream = new CustomBufferedStream(serverStream, bufferPool, 4096)
var serverSslHelloInfo = await SslTools.PeekServerHello(yourServerStream, bufferPool);

//will be null if no server hello was received (not a SSL connection)
if(serverSslHelloInfo!=null)
Expand Down
47 changes: 47 additions & 0 deletions StreamExtended/BufferPool/DefaultBufferPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Collections.Concurrent;

namespace StreamExtended
{

/// <summary>
/// A concrete IBufferPool implementation using a thread-safe stack.
/// Works well when all consumers ask for buffers with the same size.
/// If your application would use size buffers consider implementing IBufferPool using System.Buffers library from Microsoft.
/// </summary>
public class DefaultBufferPool : IBufferPool
{
private readonly ConcurrentStack<byte[]> buffers = new ConcurrentStack<byte[]>();

/// <summary>
/// Gets a buffer.
/// </summary>
/// <param name="bufferSize">Size of the buffer.</param>
/// <returns></returns>
public byte[] GetBuffer(int bufferSize)
{
if (!buffers.TryPop(out var buffer) || buffer.Length != bufferSize)
{
buffer = new byte[bufferSize];
}

return buffer;
}

/// <summary>
/// Returns the buffer.
/// </summary>
/// <param name="buffer">The buffer.</param>
public void ReturnBuffer(byte[] buffer)
{
if (buffer != null)
{
buffers.Push(buffer);
}
}

public void Dispose()
{
buffers.Clear();
}
}
}
14 changes: 14 additions & 0 deletions StreamExtended/BufferPool/IBufferPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace StreamExtended
{
/// <summary>
/// Use this interface to implement custom buffer pool.
/// To use the default buffer pool implementation use DefaultBufferPool class.
/// </summary>
public interface IBufferPool : IDisposable
{
byte[] GetBuffer(int bufferSize);
void ReturnBuffer(byte[] buffer);
}
}
3 changes: 3 additions & 0 deletions StreamExtended/ClientHelloInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

namespace StreamExtended
{
/// <summary>
/// Wraps up the client SSL hello information.
/// </summary>
public class ClientHelloInfo
{
private static readonly string[] compressions = {
Expand Down
36 changes: 0 additions & 36 deletions StreamExtended/Helpers/BufferPool.cs

This file was deleted.

3 changes: 3 additions & 0 deletions StreamExtended/Models/SslExtension.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace StreamExtended.Models
{
/// <summary>
/// The SSL extension information.
/// </summary>
public class SslExtension
{
/// <summary>
Expand Down
5 changes: 3 additions & 2 deletions StreamExtended/Network/ClientHelloAlpnAdderStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ namespace StreamExtended.Network
public class ClientHelloAlpnAdderStream : Stream
{
private readonly CustomBufferedStream stream;
private readonly IBufferPool bufferPool;

private bool called;

public ClientHelloAlpnAdderStream(CustomBufferedStream stream)
public ClientHelloAlpnAdderStream(CustomBufferedStream stream, IBufferPool bufferPool)
{
this.stream = stream;
}
Expand Down Expand Up @@ -49,7 +50,7 @@ public override void Write(byte[] buffer, int offset, int count)

//this can be non async, because reads from a memory stream
var cts = new CancellationTokenSource();
var clientHello = SslTools.PeekClientHello(new CustomBufferedStream(ms, (int)ms.Length), cts.Token).Result;
var clientHello = SslTools.PeekClientHello(new CustomBufferedStream(ms, bufferPool, (int)ms.Length), bufferPool, cts.Token).Result;
if (clientHello != null)
{
// 0x00 0x10: ALPN identifier
Expand Down
17 changes: 11 additions & 6 deletions StreamExtended/Network/CopyStream.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Helpers;

namespace StreamExtended.Network
{
/// <summary>
/// Copies the source stream to destination stream.
/// But this let users to peek and read the copying process.
/// </summary>
public class CopyStream : ICustomStreamReader, IDisposable
{
private readonly ICustomStreamReader reader;

private readonly ICustomStreamWriter writer;

private readonly IBufferPool bufferPool;

public int BufferSize { get; }

private int bufferLength;
Expand All @@ -25,12 +30,12 @@ public class CopyStream : ICustomStreamReader, IDisposable

public long ReadBytes { get; private set; }

public CopyStream(ICustomStreamReader reader, ICustomStreamWriter writer, int bufferSize)
public CopyStream(ICustomStreamReader reader, ICustomStreamWriter writer, IBufferPool bufferPool, int bufferSize)
{
this.reader = reader;
this.writer = writer;
BufferSize = bufferSize;
buffer = BufferPool.GetBuffer(bufferSize);
buffer = bufferPool.GetBuffer(bufferSize);
}

public async Task<bool> FillBufferAsync(CancellationToken cancellationToken = default(CancellationToken))
Expand Down Expand Up @@ -117,17 +122,17 @@ public int Read(byte[] buffer, int offset, int count)

public Task<string> ReadLineAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return CustomBufferedStream.ReadLineInternalAsync(this, cancellationToken);
return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken);
}

public void Dispose()
{
if (!disposed)
{
disposed = true;
var buf = buffer;
var b = buffer;
buffer = null;
BufferPool.ReturnBuffer(buf);
bufferPool.ReturnBuffer(b);
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions StreamExtended/Network/CustomBufferedPeekStream.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
using System;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;

namespace StreamExtended.Network
{
public class CustomBufferedPeekStream : ICustomStreamReader
internal class CustomBufferedPeekStream : ICustomStreamReader
{
private readonly IBufferPool bufferPool;
private readonly ICustomStreamReader baseStream;

internal int Position { get; private set; }

internal CustomBufferedPeekStream(ICustomStreamReader baseStream, int startPosition = 0)
internal CustomBufferedPeekStream(ICustomStreamReader baseStream, IBufferPool bufferPool, int startPosition = 0)
{
this.bufferPool = bufferPool;
this.baseStream = baseStream;
Position = startPosition;
}
Expand Down Expand Up @@ -130,7 +131,7 @@ Task<int> ICustomStreamReader.ReadAsync(byte[] buffer, int offset, int count, Ca
/// <returns></returns>
Task<string> ICustomStreamReader.ReadLineAsync(CancellationToken cancellationToken)
{
return CustomBufferedStream.ReadLineInternalAsync(this, cancellationToken);
return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken);
}

}
Expand Down
31 changes: 17 additions & 14 deletions StreamExtended/Network/CustomBufferedStream.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using StreamExtended.Helpers;
using System;
using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
Expand All @@ -10,8 +8,9 @@
namespace StreamExtended.Network
{
/// <summary>
/// A custom network stream inherited from stream
/// with an underlying buffer
/// A custom network stream inherited from stream
/// with an underlying read buffer supporting both read/write
/// of UTF-8 encoded string or raw bytes asynchronously from last read position.
/// </summary>
/// <seealso cref="System.IO.Stream" />
public class CustomBufferedStream : Stream, ICustomStreamReader
Expand All @@ -31,6 +30,8 @@ public class CustomBufferedStream : Stream, ICustomStreamReader

private bool closed;

private readonly IBufferPool bufferPool;

public int BufferSize { get; }

public event EventHandler<DataEventArgs> DataRead;
Expand All @@ -41,14 +42,16 @@ public class CustomBufferedStream : Stream, ICustomStreamReader
/// Initializes a new instance of the <see cref="CustomBufferedStream"/> class.
/// </summary>
/// <param name="baseStream">The base stream.</param>
/// <param name="bufferPool">Bufferpool.</param>
/// <param name="bufferSize">Size of the buffer.</param>
/// <param name="leaveOpen"><see langword="true" /> to leave the stream open after disposing the <see cref="T:CustomBufferedStream" /> object; otherwise, <see langword="false" />.</param>
public CustomBufferedStream(Stream baseStream, int bufferSize, bool leaveOpen = false)
public CustomBufferedStream(Stream baseStream, IBufferPool bufferPool, int bufferSize, bool leaveOpen = false)
{
this.baseStream = baseStream;
BufferSize = bufferSize;
this.leaveOpen = leaveOpen;
streamBuffer = BufferPool.GetBuffer(bufferSize);
streamBuffer = bufferPool.GetBuffer(bufferSize);
this.bufferPool = bufferPool;
}

/// <summary>
Expand Down Expand Up @@ -291,7 +294,7 @@ public byte ReadByteFromBuffer()
/// <param name="value">The byte to write to the stream.</param>
public override void WriteByte(byte value)
{
var buffer = BufferPool.GetBuffer(BufferSize);
var buffer = bufferPool.GetBuffer(BufferSize);
try
{
buffer[0] = value;
Expand All @@ -300,7 +303,7 @@ public override void WriteByte(byte value)
}
finally
{
BufferPool.ReturnBuffer(buffer);
bufferPool.ReturnBuffer(buffer);
}
}

Expand Down Expand Up @@ -331,7 +334,7 @@ protected override void Dispose(bool disposing)

var buffer = streamBuffer;
streamBuffer = null;
BufferPool.ReturnBuffer(buffer);
bufferPool.ReturnBuffer(buffer);
}
}

Expand Down Expand Up @@ -493,21 +496,21 @@ public bool FillBuffer()
/// <returns></returns>
public Task<string> ReadLineAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ReadLineInternalAsync(this, cancellationToken);
return ReadLineInternalAsync(this, bufferPool, cancellationToken);
}

/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
internal static async Task<string> ReadLineInternalAsync(ICustomStreamReader reader, CancellationToken cancellationToken = default(CancellationToken))
internal static async Task<string> ReadLineInternalAsync(ICustomStreamReader reader, IBufferPool bufferPool, CancellationToken cancellationToken = default(CancellationToken))
{
byte lastChar = default(byte);

int bufferDataLength = 0;

// try to use buffer from the buffer pool, usually it is enough
var bufferPoolBuffer = BufferPool.GetBuffer(reader.BufferSize);
var bufferPoolBuffer = bufferPool.GetBuffer(reader.BufferSize);
var buffer = bufferPoolBuffer;

try
Expand Down Expand Up @@ -541,7 +544,7 @@ public bool FillBuffer()
}
finally
{
BufferPool.ReturnBuffer(bufferPoolBuffer);
bufferPool.ReturnBuffer(bufferPoolBuffer);
}

if (bufferDataLength == 0)
Expand Down
2 changes: 1 addition & 1 deletion StreamExtended/Network/DataEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace StreamExtended.Network
{
/// <summary>
/// Wraps the data sent/received by a proxy server instance.
/// Wraps the data sent/received event argument.
/// </summary>
public class DataEventArgs : EventArgs
{
Expand Down
3 changes: 3 additions & 0 deletions StreamExtended/Network/ICustomStreamReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

namespace StreamExtended.Network
{
/// <summary>
/// This concrete implemetation of interface acts as the source stream for CopyStream class.
/// </summary>
public interface ICustomStreamReader
{
int BufferSize { get; }
Expand Down
Loading

0 comments on commit ec04103

Please sign in to comment.