initial commit
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Crysome.Client.Handlers;
|
||||
|
||||
internal sealed class ReverseProxyStream : Stream
|
||||
{
|
||||
private readonly Queue<byte[]> _chunks = new Queue<byte[]>();
|
||||
|
||||
private byte[] _currentChunk;
|
||||
|
||||
private int _currentOffset;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private bool _closed;
|
||||
|
||||
private readonly Action<byte[]> _sendToServer;
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public ReverseProxyStream(Action<byte[]> sendToServer)
|
||||
{
|
||||
_sendToServer = sendToServer ?? throw new ArgumentNullException("sendToServer");
|
||||
}
|
||||
|
||||
public void Push(byte[] data)
|
||||
{
|
||||
if (data == null || data.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_closed)
|
||||
{
|
||||
_chunks.Enqueue(data);
|
||||
Monitor.Pulse(_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CloseFromRemote()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_closed = true;
|
||||
Monitor.PulseAll(_lock);
|
||||
}
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer == null || offset < 0 || count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
int num = 0;
|
||||
while (num < count)
|
||||
{
|
||||
if (_currentChunk != null && _currentOffset < _currentChunk.Length)
|
||||
{
|
||||
int num2 = Math.Min(count - num, _currentChunk.Length - _currentOffset);
|
||||
Array.Copy(_currentChunk, _currentOffset, buffer, offset + num, num2);
|
||||
_currentOffset += num2;
|
||||
num += num2;
|
||||
if (_currentOffset >= _currentChunk.Length)
|
||||
{
|
||||
_currentChunk = null;
|
||||
_currentOffset = 0;
|
||||
}
|
||||
if (num > 0)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
}
|
||||
if (_chunks.Count > 0)
|
||||
{
|
||||
_currentChunk = _chunks.Dequeue();
|
||||
_currentOffset = 0;
|
||||
continue;
|
||||
}
|
||||
if (_closed)
|
||||
{
|
||||
return (num > 0) ? num : 0;
|
||||
}
|
||||
Monitor.Wait(_lock);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer != null && count > 0 && offset >= 0 && offset + count <= buffer.Length)
|
||||
{
|
||||
byte[] array = new byte[count];
|
||||
Array.Copy(buffer, offset, array, 0, count);
|
||||
_sendToServer(array);
|
||||
}
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user