Commit acad670d authored by Jehonathan's avatar Jehonathan Committed by GitHub

Merge pull request #259 from justcoding121/beta

Push dispose fix on buffered stream to stable
parents f5a6fe91 d0f7c099
......@@ -13,10 +13,9 @@ namespace Titanium.Web.Proxy.Helpers
internal class CustomBinaryReader : IDisposable
{
private readonly CustomBufferedStream stream;
private readonly int bufferSize;
private readonly Encoding encoding;
private volatile bool disposed;
private bool disposed;
internal byte[] Buffer { get; }
......@@ -24,7 +23,6 @@ namespace Titanium.Web.Proxy.Helpers
{
this.stream = stream;
Buffer = BufferPool.GetBuffer(bufferSize);
this.bufferSize = bufferSize;
//default to UTF-8
encoding = Encoding.UTF8;
......
......@@ -14,14 +14,20 @@ namespace Titanium.Web.Proxy.Helpers
/// <seealso cref="System.IO.Stream" />
internal class CustomBufferedStream : Stream
{
private AsyncCallback readCallback;
private readonly Stream baseStream;
private byte[] streamBuffer;
private readonly byte[] oneByteBuffer = new byte[1];
private int bufferLength;
private int bufferPos;
private bool disposed;
/// <summary>
/// Initializes a new instance of the <see cref="CustomBufferedStream"/> class.
/// </summary>
......@@ -29,6 +35,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="bufferSize">Size of the buffer.</param>
public CustomBufferedStream(Stream baseStream, int bufferSize)
{
readCallback = new AsyncCallback(ReadCallback);
this.baseStream = baseStream;
streamBuffer = BufferPool.GetBuffer(bufferSize);
}
......@@ -100,6 +107,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="count">The number of bytes to be written to the current stream.</param>
public override void Write(byte[] buffer, int offset, int count)
{
OnDataSent(buffer, offset, count);
baseStream.Write(buffer, offset, count);
}
......@@ -123,10 +131,19 @@ namespace Titanium.Web.Proxy.Helpers
Buffer.BlockCopy(streamBuffer, bufferPos, buffer, offset, available);
bufferPos += available;
bufferLength -= available;
return new ReadAsyncResult(available);
return new ReadAsyncResult(buffer, offset, available, state, callback);
}
return baseStream.BeginRead(buffer, offset, count, callback, state);
var result = new ReadAsyncResult(buffer, offset, 0, state, callback);
result.BaseResult = baseStream.BeginRead(buffer, offset, count, readCallback, result);
return result;
}
private void ReadCallback(IAsyncResult ar)
{
var readResult = (ReadAsyncResult)ar.AsyncState;
readResult.BaseResult = ar;
readResult.Callback(readResult);
}
/// <summary>
......@@ -143,6 +160,7 @@ namespace Titanium.Web.Proxy.Helpers
[DebuggerStepThrough]
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
OnDataSent(buffer, offset, count);
return baseStream.BeginWrite(buffer, offset, count, callback, state);
}
......@@ -163,7 +181,7 @@ namespace Titanium.Web.Proxy.Helpers
bufferLength = 0;
}
await baseStream.CopyToAsync(destination, bufferSize, cancellationToken);
await base.CopyToAsync(destination, bufferSize, cancellationToken);
}
/// <summary>
......@@ -188,12 +206,11 @@ namespace Titanium.Web.Proxy.Helpers
[DebuggerStepThrough]
public override int EndRead(IAsyncResult asyncResult)
{
if (asyncResult is ReadAsyncResult)
{
return ((ReadAsyncResult)asyncResult).ReadBytes;
}
var readResult = (ReadAsyncResult)asyncResult;
int result = readResult.BaseResult == null ? readResult.ReadBytes : baseStream.EndRead(readResult.BaseResult);
return baseStream.EndRead(asyncResult);
OnDataReceived(readResult.Buffer, readResult.Offset, result);
return result;
}
/// <summary>
......@@ -313,6 +330,7 @@ namespace Titanium.Web.Proxy.Helpers
[DebuggerStepThrough]
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
OnDataSent(buffer, offset, count);
return baseStream.WriteAsync(buffer, offset, count, cancellationToken);
}
......@@ -322,7 +340,17 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="value">The byte to write to the stream.</param>
public override void WriteByte(byte value)
{
baseStream.WriteByte(value);
oneByteBuffer[0] = value;
OnDataSent(oneByteBuffer, 0, 1);
baseStream.Write(oneByteBuffer, 0, 1);
}
private void OnDataSent(byte[] buffer, int offset, int count)
{
}
private void OnDataReceived(byte[] buffer, int offset, int count)
{
}
/// <summary>
......@@ -331,9 +359,15 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
baseStream.Dispose();
BufferPool.ReturnBuffer(streamBuffer);
streamBuffer = null;
if(!disposed)
{
disposed = true;
baseStream.Dispose();
BufferPool.ReturnBuffer(streamBuffer);
streamBuffer = null;
readCallback = null;
}
}
/// <summary>
......@@ -397,6 +431,11 @@ namespace Titanium.Web.Proxy.Helpers
{
bufferLength = baseStream.Read(streamBuffer, 0, streamBuffer.Length);
bufferPos = 0;
if (bufferLength > 0)
{
OnDataReceived(streamBuffer, 0, bufferLength);
}
return bufferLength > 0;
}
......@@ -418,24 +457,41 @@ namespace Titanium.Web.Proxy.Helpers
{
bufferLength = await baseStream.ReadAsync(streamBuffer, 0, streamBuffer.Length, cancellationToken);
bufferPos = 0;
if (bufferLength > 0)
{
OnDataReceived(streamBuffer, 0, bufferLength);
}
return bufferLength > 0;
}
private class ReadAsyncResult : IAsyncResult
{
public byte[] Buffer { get; }
public int Offset { get; }
public IAsyncResult BaseResult { get; set; }
public int ReadBytes { get; }
public bool IsCompleted => true;
public object AsyncState { get; }
public AsyncCallback Callback { get; }
public WaitHandle AsyncWaitHandle => null;
public bool IsCompleted => CompletedSynchronously || BaseResult.IsCompleted;
public object AsyncState => null;
public WaitHandle AsyncWaitHandle => BaseResult?.AsyncWaitHandle;
public bool CompletedSynchronously => true;
public bool CompletedSynchronously => BaseResult == null || BaseResult.CompletedSynchronously;
public ReadAsyncResult(int readBytes)
public ReadAsyncResult(byte[] buffer, int offset, int readBytes, object state, AsyncCallback callback)
{
Buffer = buffer;
Offset = offset;
ReadBytes = readBytes;
AsyncState = state;
Callback = callback;
}
}
}
......
......@@ -276,6 +276,46 @@ namespace Titanium.Web.Proxy.Network
RemoveTrustedRootCertificates(StoreLocation.LocalMachine);
}
/// <summary>
/// Removes the trusted certificates from the local machine's certificate store.
/// Needs elevated permission. Works only on Windows.
/// </summary>
/// <returns></returns>
public bool RemoveTrustedRootCertificatesAsAdministrator()
{
if (RunTime.IsRunningOnMono)
{
return false;
}
var info = new ProcessStartInfo
{
FileName = "certutil.exe",
Arguments = "-delstore Root \"" + RootCertificateName + "\"",
CreateNoWindow = true,
UseShellExecute = true,
Verb = "runas",
ErrorDialog = false,
};
try
{
var process = Process.Start(info);
if (process == null)
{
return false;
}
process.WaitForExit();
}
catch
{
return false;
}
return true;
}
/// <summary>
/// Determines whether the root certificate is trusted.
/// </summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment