Unverified Commit f9a74d7b authored by honfika's avatar honfika Committed by GitHub

Merge pull request #691 from justcoding121/master

less exceptions
parents b81baeca 4febcb05
...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
proxyServer.EnableHttp2 = true; //proxyServer.EnableHttp2 = true;
// generate root certificate without storing it in file system // generate root certificate without storing it in file system
//proxyServer.CertificateManager.CreateRootCertificate(false); //proxyServer.CertificateManager.CreateRootCertificate(false);
......
...@@ -141,26 +141,29 @@ namespace Titanium.Web.Proxy ...@@ -141,26 +141,29 @@ namespace Titanium.Web.Proxy
bool http2Supported = false; bool http2Supported = false;
var alpn = clientHelloInfo.GetAlpn(); if (EnableHttp2)
if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
{ {
// test server HTTP/2 support var alpn = clientHelloInfo.GetAlpn();
try if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
{
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, SslExtensions.Http2ProtocolAsList,
true, cancellationToken);
http2Supported = connection.NegotiatedApplicationProtocol ==
SslApplicationProtocol.Http2;
// release connection back to pool instead of closing when connection pool is enabled.
await tcpConnectionFactory.Release(connection, true);
}
catch (Exception)
{ {
// ignore // test server HTTP/2 support
try
{
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, SslExtensions.Http2ProtocolAsList,
true, cancellationToken);
http2Supported = connection.NegotiatedApplicationProtocol ==
SslApplicationProtocol.Http2;
// release connection back to pool instead of closing when connection pool is enabled.
await tcpConnectionFactory.Release(connection, true);
}
catch (Exception)
{
// ignore
}
} }
} }
...@@ -274,7 +277,7 @@ namespace Titanium.Web.Proxy ...@@ -274,7 +277,7 @@ namespace Titanium.Web.Proxy
// If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then // If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
// this connection should not be HTTPS. // this connection should not be HTTPS.
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs, var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
true, SslExtensions.Http2ProtocolAsList, true, null,
true, cancellationToken); true, cancellationToken);
try try
......
...@@ -33,7 +33,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -33,7 +33,8 @@ namespace Titanium.Web.Proxy.Helpers
private bool disposed; private bool disposed;
private bool closed; private bool closedWrite;
private bool closedRead;
private readonly IBufferPool bufferPool; private readonly IBufferPool bufferPool;
...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy.Helpers
private Stream baseStream { get; } private Stream baseStream { get; }
public bool IsClosed => closed; public bool IsClosed => closedRead;
static HttpStream() static HttpStream()
{ {
...@@ -89,7 +90,21 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -89,7 +90,21 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
public override void Flush() public override void Flush()
{ {
baseStream.Flush(); if (closedWrite)
{
return;
}
try
{
baseStream.Flush();
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
} }
/// <summary> /// <summary>
...@@ -153,7 +168,22 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -153,7 +168,22 @@ namespace Titanium.Web.Proxy.Helpers
public override void Write(byte[] buffer, int offset, int count) public override void Write(byte[] buffer, int offset, int count)
{ {
OnDataWrite(buffer, offset, count); OnDataWrite(buffer, offset, count);
baseStream.Write(buffer, offset, count);
if (closedWrite)
{
return;
}
try
{
baseStream.Write(buffer, offset, count);
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
} }
/// <summary> /// <summary>
...@@ -184,9 +214,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -184,9 +214,23 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns> /// <returns>
/// A task that represents the asynchronous flush operation. /// A task that represents the asynchronous flush operation.
/// </returns> /// </returns>
public override Task FlushAsync(CancellationToken cancellationToken) public override async Task FlushAsync(CancellationToken cancellationToken)
{ {
return baseStream.FlushAsync(cancellationToken); if (closedWrite)
{
return;
}
try
{
await baseStream.FlushAsync(cancellationToken);
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
} }
/// <summary> /// <summary>
...@@ -393,7 +437,22 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -393,7 +437,22 @@ namespace Titanium.Web.Proxy.Helpers
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
OnDataWrite(buffer, offset, count); OnDataWrite(buffer, offset, count);
await baseStream.WriteAsync(buffer, offset, count, cancellationToken);
if (closedWrite)
{
return;
}
try
{
await baseStream.WriteAsync(buffer, offset, count, cancellationToken);
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
} }
/// <summary> /// <summary>
...@@ -402,6 +461,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -402,6 +461,11 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="value">The byte to write to the stream.</param> /// <param name="value">The byte to write to the stream.</param>
public override void WriteByte(byte value) public override void WriteByte(byte value)
{ {
if (closedWrite)
{
return;
}
var buffer = bufferPool.GetBuffer(); var buffer = bufferPool.GetBuffer();
try try
{ {
...@@ -409,6 +473,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -409,6 +473,12 @@ namespace Titanium.Web.Proxy.Helpers
OnDataWrite(buffer, 0, 1); OnDataWrite(buffer, 0, 1);
baseStream.Write(buffer, 0, 1); baseStream.Write(buffer, 0, 1);
} }
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
finally finally
{ {
bufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
...@@ -434,7 +504,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -434,7 +504,8 @@ namespace Titanium.Web.Proxy.Helpers
if (!disposed) if (!disposed)
{ {
disposed = true; disposed = true;
closed = true; closedRead = true;
closedWrite = true;
if (!leaveOpen) if (!leaveOpen)
{ {
baseStream.Dispose(); baseStream.Dispose();
...@@ -511,7 +582,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -511,7 +582,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
public bool FillBuffer() public bool FillBuffer()
{ {
if (closed) if (closedRead)
{ {
throw new Exception("Stream is already closed"); throw new Exception("Stream is already closed");
} }
...@@ -536,11 +607,17 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -536,11 +607,17 @@ namespace Titanium.Web.Proxy.Helpers
bufferLength += readBytes; bufferLength += readBytes;
} }
} }
catch
{
if (!swallowException)
throw;
}
finally finally
{ {
if (!result) if (!result)
{ {
closed = true; closedRead = true;
closedWrite = true;
} }
} }
...@@ -555,7 +632,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -555,7 +632,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns> /// <returns></returns>
public async ValueTask<bool> FillBufferAsync(CancellationToken cancellationToken = default) public async ValueTask<bool> FillBufferAsync(CancellationToken cancellationToken = default)
{ {
if (closed) if (closedRead)
{ {
throw new Exception("Stream is already closed"); throw new Exception("Stream is already closed");
} }
...@@ -595,7 +672,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -595,7 +672,8 @@ namespace Titanium.Web.Proxy.Helpers
{ {
if (!result) if (!result)
{ {
closed = true; closedRead = true;
closedWrite = true;
} }
} }
...@@ -766,6 +844,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -766,6 +844,11 @@ namespace Titanium.Web.Proxy.Helpers
private async ValueTask writeAsyncInternal(string value, bool addNewLine, CancellationToken cancellationToken) private async ValueTask writeAsyncInternal(string value, bool addNewLine, CancellationToken cancellationToken)
{ {
if (closedWrite)
{
return;
}
int newLineChars = addNewLine ? newLine.Length : 0; int newLineChars = addNewLine ? newLine.Length : 0;
int charCount = value.Length; int charCount = value.Length;
if (charCount < bufferPool.BufferSize - newLineChars) if (charCount < bufferPool.BufferSize - newLineChars)
...@@ -782,6 +865,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -782,6 +865,12 @@ namespace Titanium.Web.Proxy.Helpers
await baseStream.WriteAsync(buffer, 0, idx, cancellationToken); await baseStream.WriteAsync(buffer, 0, idx, cancellationToken);
} }
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
finally finally
{ {
bufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
...@@ -797,7 +886,16 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -797,7 +886,16 @@ namespace Titanium.Web.Proxy.Helpers
idx += newLineChars; idx += newLineChars;
} }
await baseStream.WriteAsync(buffer, 0, idx, cancellationToken); try
{
await baseStream.WriteAsync(buffer, 0, idx, cancellationToken);
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
} }
} }
...@@ -826,20 +924,48 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -826,20 +924,48 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
internal async ValueTask WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default) internal async ValueTask WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default)
{ {
await baseStream.WriteAsync(data, 0, data.Length, cancellationToken); if (closedWrite)
if (flush)
{ {
await baseStream.FlushAsync(cancellationToken); return;
}
try
{
await baseStream.WriteAsync(data, 0, data.Length, cancellationToken);
if (flush)
{
await baseStream.FlushAsync(cancellationToken);
}
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
} }
} }
internal async Task WriteAsync(byte[] data, int offset, int count, bool flush, internal async Task WriteAsync(byte[] data, int offset, int count, bool flush,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
await baseStream.WriteAsync(data, offset, count, cancellationToken); if (closedWrite)
if (flush)
{ {
await baseStream.FlushAsync(cancellationToken); return;
}
try
{
await baseStream.WriteAsync(data, offset, count, cancellationToken);
if (flush)
{
await baseStream.FlushAsync(cancellationToken);
}
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
} }
} }
...@@ -1056,9 +1182,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -1056,9 +1182,23 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="buffer">The buffer to write data from.</param> /// <param name="buffer">The buffer to write data from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>A task that represents the asynchronous write operation.</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{ {
return baseStream.WriteAsync(buffer, cancellationToken); if (closedWrite)
{
return;
}
try
{
await baseStream.WriteAsync(buffer, cancellationToken);
}
catch
{
closedWrite = true;
if (!swallowException)
throw;
}
} }
#else #else
/// <summary> /// <summary>
...@@ -1067,11 +1207,19 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -1067,11 +1207,19 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="buffer">The buffer to write data from.</param> /// <param name="buffer">The buffer to write data from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>A task that represents the asynchronous write operation.</returns> /// <returns>A task that represents the asynchronous write operation.</returns>
public Task WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken) public async Task WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
{ {
var buf = ArrayPool<byte>.Shared.Rent(buffer.Length); var buf = ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.CopyTo(buf); buffer.CopyTo(buf);
return baseStream.WriteAsync(buf, 0, buf.Length, cancellationToken); try
{
await baseStream.WriteAsync(buf, 0, buf.Length, cancellationToken);
}
catch
{
if (!swallowException)
throw;
}
} }
#endif #endif
} }
......
...@@ -2,33 +2,33 @@ ...@@ -2,33 +2,33 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
internal class NullWriter : IHttpStreamWriter namespace Titanium.Web.Proxy.Helpers
{ {
public static NullWriter Instance { get; } = new NullWriter(); internal class NullWriter : IHttpStreamWriter
public void Write(byte[] buffer, int offset, int count)
{ {
} public static NullWriter Instance { get; } = new NullWriter();
#if NET45 public void Write(byte[] buffer, int offset, int count)
public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) {
{ }
}
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
#if NET45
return Net45Compatibility.CompletedTask;
#else #else
public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) return Task.CompletedTask;
{
return Task.CompletedTask;
}
#endif #endif
}
public ValueTask WriteLineAsync(CancellationToken cancellationToken = default) public ValueTask WriteLineAsync(CancellationToken cancellationToken = default)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public ValueTask WriteLineAsync(string value, CancellationToken cancellationToken = default) public ValueTask WriteLineAsync(string value, CancellationToken cancellationToken = default)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
}
} }
} }
...@@ -10,6 +10,8 @@ namespace Titanium.Web.Proxy ...@@ -10,6 +10,8 @@ namespace Titanium.Web.Proxy
class Net45Compatibility class Net45Compatibility
{ {
public static byte[] EmptyArray = new byte[0]; public static byte[] EmptyArray = new byte[0];
public static Task CompletedTask = new Task(() => { });
} }
} }
#endif #endif
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