diff --git a/.build/build.ps1 b/.build/build.ps1
index e98be4697..f5f517709 100644
--- a/.build/build.ps1
+++ b/.build/build.ps1
@@ -29,7 +29,7 @@ if($Branch -eq "beta" ) { $Version = "$Version-beta" }
$NuGet = Join-Path $RepoRoot ".nuget\nuget.exe"
-$MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe"
+$MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe"
$MSBuild -replace ' ', '` '
FormatTaskName (("-"*25) + "[{0}]" + ("-"*25))
diff --git a/appveyor.yml b/appveyor.yml
index 5ec39fb99..9930bd74d 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -8,7 +8,7 @@
# version format
version: 3.1.{build}
-image: Visual Studio 2017
+image: Visual Studio 2019
shallow_clone: false
diff --git a/examples/Titanium.Web.Proxy.Examples.Wpf/Titanium.Web.Proxy.Examples.Wpf.csproj b/examples/Titanium.Web.Proxy.Examples.Wpf/Titanium.Web.Proxy.Examples.Wpf.csproj
index 90ad8f247..89dd81498 100644
--- a/examples/Titanium.Web.Proxy.Examples.Wpf/Titanium.Web.Proxy.Examples.Wpf.csproj
+++ b/examples/Titanium.Web.Proxy.Examples.Wpf/Titanium.Web.Proxy.Examples.Wpf.csproj
@@ -6,11 +6,11 @@
true
-
+
@@ -20,23 +20,6 @@
-
+
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy.sln b/src/Titanium.Web.Proxy.sln
index 8949754d1..70d4696f7 100644
--- a/src/Titanium.Web.Proxy.sln
+++ b/src/Titanium.Web.Proxy.sln
@@ -68,6 +68,7 @@ Global
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|x64.ActiveCfg = Debug|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|x64.Build.0 = Debug|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.Build.0 = Release|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.ActiveCfg = Release|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.Build.0 = Release|Any CPU
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -89,7 +90,7 @@ Global
{1D053D72-DCB4-4517-ACDD-D35ADC186950} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {625C1EB5-44CF-47DE-A85A-B4C8C40ED90A}
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
+ SolutionGuid = {625C1EB5-44CF-47DE-A85A-B4C8C40ED90A}
EndGlobalSection
EndGlobal
diff --git a/src/Titanium.Web.Proxy/ExplicitClientHandler.cs b/src/Titanium.Web.Proxy/ExplicitClientHandler.cs
index 6a94d096f..6035beaed 100644
--- a/src/Titanium.Web.Proxy/ExplicitClientHandler.cs
+++ b/src/Titanium.Web.Proxy/ExplicitClientHandler.cs
@@ -288,8 +288,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
if (!clientStream.IsClosed && !connection.Stream.IsClosed)
{
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
- null, null,
- connectArgs.CancellationTokenSource, ExceptionFunc);
+ null, null, connectArgs.CancellationTokenSource, ExceptionFunc);
}
}
finally
@@ -338,17 +337,15 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
await connection.StreamWriter.WriteLineAsync("SM", cancellationToken);
await connection.StreamWriter.WriteLineAsync(cancellationToken);
#if NETCOREAPP2_1
- await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferPool.BufferSize,
- (buffer, offset, count) => { connectArgs.OnDecryptedDataSent(buffer, offset, count); },
- (buffer, offset, count) => { connectArgs.OnDecryptedDataReceived(buffer, offset, count); },
+ await Http2Helper.SendHttp2(clientStream, connection.Stream,
() => new SessionEventArgs(this, endPoint, cancellationTokenSource)
{
ProxyClient = { Connection = clientConnection },
HttpClient = { ConnectRequest = connectArgs?.HttpClient.ConnectRequest },
UserData = connectArgs?.UserData
},
- async args => { await invokeBeforeRequest(args); },
- async args => { await invokeBeforeResponse(args); },
+ async args => { await onBeforeRequest(args); },
+ async args => { await onBeforeResponse(args); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif
}
diff --git a/src/Titanium.Web.Proxy/Extensions/SslExtensions.cs b/src/Titanium.Web.Proxy/Extensions/SslExtensions.cs
index 6af5801b1..81ccd9324 100644
--- a/src/Titanium.Web.Proxy/Extensions/SslExtensions.cs
+++ b/src/Titanium.Web.Proxy/Extensions/SslExtensions.cs
@@ -28,7 +28,7 @@ internal static string GetServerName(this ClientHelloInfo clientHelloInfo)
return null;
}
-#if NETCOREAPP2_1
+#if NETCOREAPP2_1 || NETSTANDARD2_1
internal static List GetAlpn(this ClientHelloInfo clientHelloInfo)
{
if (clientHelloInfo.Extensions != null && clientHelloInfo.Extensions.TryGetValue("ALPN", out var alpnExtension))
@@ -78,7 +78,7 @@ internal static Task AuthenticateAsServerAsync(this SslStream sslStream, SslServ
#endif
}
-#if !NETCOREAPP2_1
+#if !NETCOREAPP2_1 && !NETSTANDARD2_1
internal enum SslApplicationProtocol
{
Http11,
diff --git a/src/Titanium.Web.Proxy/Helpers/HttpHelper.cs b/src/Titanium.Web.Proxy/Helpers/HttpHelper.cs
index 2ddd6f6fc..a649f91bd 100644
--- a/src/Titanium.Web.Proxy/Helpers/HttpHelper.cs
+++ b/src/Titanium.Web.Proxy/Helpers/HttpHelper.cs
@@ -151,20 +151,28 @@ internal static Task IsPriMethod(ICustomStreamReader clientStreamReader, IB
///
private static async Task startsWith(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, string expectedStart, CancellationToken cancellationToken = default)
{
- int iRet = -1;
const int lengthToCheck = 10;
byte[] buffer = null;
try
{
- buffer = bufferPool.GetBuffer(Math.Max(bufferPool.BufferSize, lengthToCheck));
+ if (bufferPool.BufferSize < lengthToCheck)
+ {
+ throw new Exception($"Buffer is too small. Minimum size is {lengthToCheck} bytes");
+ }
- int peeked = await clientStreamReader.PeekBytesAsync(buffer, 0, 0, lengthToCheck, cancellationToken);
+ buffer = bufferPool.GetBuffer(bufferPool.BufferSize);
- if (peeked > 0)
+ bool isExpected = true;
+ int i = 0;
+ while (i < lengthToCheck)
{
- bool isExpected = true;
+ int peeked = await clientStreamReader.PeekBytesAsync(buffer, i, i, lengthToCheck - i, cancellationToken);
+ if (peeked == 0)
+ return - 1;
+
+ peeked += i;
- for (int i = 0; i < lengthToCheck; i++)
+ while (i < peeked)
{
int b = buffer[i];
@@ -173,23 +181,23 @@ private static async Task startsWith(ICustomStreamReader clientStreamReader
else
{
char ch = (char)b;
- if (!char.IsLetter(ch))
+ if (ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) // ASCII letter
return -1;
else if (i >= expectedStart.Length || ch != expectedStart[i])
- isExpected = false;
+ isExpected = false;
}
- }
- // only letters
- iRet = isExpected ? 1 : 0;
+ i++;
+ }
}
+
+ // only letters
+ return 0;
}
finally
{
bufferPool.ReturnBuffer(buffer);
- buffer = null;
}
- return iRet;
}
}
}
diff --git a/src/Titanium.Web.Proxy/Http2/Http2Helper.cs b/src/Titanium.Web.Proxy/Http2/Http2Helper.cs
index 2fe85d194..185f0bda8 100644
--- a/src/Titanium.Web.Proxy/Http2/Http2Helper.cs
+++ b/src/Titanium.Web.Proxy/Http2/Http2Helper.cs
@@ -1,4 +1,4 @@
-#if NETCOREAPP2_1
+#if NETCOREAPP2_1 || NETSTANDARD2_1
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -24,8 +24,7 @@ internal class Http2Helper
/// Task-based Asynchronous Pattern
///
///
- internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize,
- Action onDataSend, Action onDataReceive,
+ internal static async Task SendHttp2(Stream clientStream, Stream serverStream,
Func sessionFactory,
Func onBeforeRequest, Func onBeforeResponse,
CancellationTokenSource cancellationTokenSource, Guid connectionId,
@@ -38,13 +37,13 @@ internal static async Task SendHttp2(Stream clientStream, Stream serverStream, i
// Now async relay all server=>client & client=>server data
var sendRelay =
- copyHttp2FrameAsync(clientStream, serverStream, onDataSend, clientSettings, serverSettings,
+ copyHttp2FrameAsync(clientStream, serverStream, clientSettings, serverSettings,
sessionFactory, sessions, onBeforeRequest,
- bufferSize, connectionId, true, cancellationTokenSource.Token, exceptionFunc);
+ connectionId, true, cancellationTokenSource.Token, exceptionFunc);
var receiveRelay =
- copyHttp2FrameAsync(serverStream, clientStream, onDataReceive, serverSettings, clientSettings,
+ copyHttp2FrameAsync(serverStream, clientStream, serverSettings, clientSettings,
sessionFactory, sessions, onBeforeResponse,
- bufferSize, connectionId, false, cancellationTokenSource.Token, exceptionFunc);
+ connectionId, false, cancellationTokenSource.Token, exceptionFunc);
await Task.WhenAny(sendRelay, receiveRelay);
cancellationTokenSource.Cancel();
@@ -52,11 +51,11 @@ internal static async Task SendHttp2(Stream clientStream, Stream serverStream, i
await Task.WhenAll(sendRelay, receiveRelay);
}
- private static async Task copyHttp2FrameAsync(Stream input, Stream output, Action onCopy,
+ private static async Task copyHttp2FrameAsync(Stream input, Stream output,
Http2Settings localSettings, Http2Settings remoteSettings,
Func sessionFactory, ConcurrentDictionary sessions,
Func onBeforeRequestResponse,
- int bufferSize, Guid connectionId, bool isClient, CancellationToken cancellationToken,
+ Guid connectionId, bool isClient, CancellationToken cancellationToken,
ExceptionHandler exceptionFunc)
{
int headerTableSize = 0;
@@ -69,7 +68,6 @@ private static async Task copyHttp2FrameAsync(Stream input, Stream output, Actio
{
var frameHeaderBuffer = frameHeader.Buffer;
int read = await forceRead(input, frameHeaderBuffer, 0, 9, cancellationToken);
- onCopy(frameHeaderBuffer, 0, read);
if (read != 9)
{
return;
@@ -92,7 +90,6 @@ private static async Task copyHttp2FrameAsync(Stream input, Stream output, Actio
}
read = await forceRead(input, buffer, 0, length, cancellationToken);
- onCopy(buffer, 0, read);
if (read != length)
{
return;
@@ -127,6 +124,11 @@ private static async Task copyHttp2FrameAsync(Stream input, Stream output, Actio
//System.Diagnostics.Debug.WriteLine("CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type);
if (type == Http2FrameType.Data && args != null)
{
+ if (isClient)
+ args.OnDataSent(buffer, 0, read);
+ else
+ args.OnDataReceived(buffer, 0, read);
+
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
bool padded = (flags & Http2FrameFlag.Padded) != 0;
@@ -182,8 +184,10 @@ private static async Task copyHttp2FrameAsync(Stream input, Stream output, Actio
{
args = sessionFactory();
args.IsPromise = true;
- sessions.TryAdd(streamId, args);
- sessions.TryAdd(promisedStreamId, args);
+ if (!sessions.TryAdd(streamId, args))
+ ;
+ if (!sessions.TryAdd(promisedStreamId, args))
+ ;
}
System.Diagnostics.Debug.WriteLine("PROMISE STREAM: " + streamId + ", " + promisedStreamId +
@@ -201,7 +205,8 @@ private static async Task copyHttp2FrameAsync(Stream input, Stream output, Actio
if (!sessions.TryGetValue(streamId, out args))
{
args = sessionFactory();
- sessions.TryAdd(streamId, args);
+ if (!sessions.TryAdd(streamId, args))
+ ;
}
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
diff --git a/src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs b/src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs
index 4e0eece06..6174406ef 100644
--- a/src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs
+++ b/src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Net;
-#if NETCOREAPP2_1
+#if NETCOREAPP2_1 || NETSTANDARD2_1
using System.Net.Security;
#endif
using System.Net.Sockets;
diff --git a/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
index 1146a66c8..39aee703d 100644
--- a/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+++ b/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
@@ -391,7 +391,7 @@ private async Task createServerConnection(string remoteHost
CertificateRevocationCheckMode = proxyServer.CheckCertificateRevocation
};
await sslStream.AuthenticateAsClientAsync(options, cancellationToken);
-#if NETCOREAPP2_1
+#if NETCOREAPP2_1 || NETSTANDARD2_1
negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif
diff --git a/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs b/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
index 93633b92e..051ee3250 100644
--- a/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
+++ b/src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
@@ -1,6 +1,6 @@
using System;
using System.Net;
-#if NETCOREAPP2_1
+#if NETCOREAPP2_1 || NETSTANDARD2_1
using System.Net.Security;
#endif
using System.Net.Sockets;
diff --git a/src/Titanium.Web.Proxy/ProxyServer.cs b/src/Titanium.Web.Proxy/ProxyServer.cs
index e67ccd145..5cf8cdc23 100644
--- a/src/Titanium.Web.Proxy/ProxyServer.cs
+++ b/src/Titanium.Web.Proxy/ProxyServer.cs
@@ -235,6 +235,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName,
/// The buffer pool used throughout this proxy instance.
/// Set custom implementations by implementing this interface.
/// By default this uses DefaultBufferPool implementation available in StreamExtended library package.
+ /// Buffer size should be at least 10 bytes.
///
public IBufferPool BufferPool { get; set; }
diff --git a/src/Titanium.Web.Proxy/RequestHandler.cs b/src/Titanium.Web.Proxy/RequestHandler.cs
index ab3701577..9bef2bbde 100644
--- a/src/Titanium.Web.Proxy/RequestHandler.cs
+++ b/src/Titanium.Web.Proxy/RequestHandler.cs
@@ -3,7 +3,7 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
-#if NETCOREAPP2_1
+#if NETCOREAPP2_1 || NETSTANDARD2_1
using System.Net.Security;
#endif
using System.Text.RegularExpressions;
@@ -143,7 +143,7 @@ await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers,
// proxy authorization check
if (httpsConnectHostname == null && await checkAuthorization(args) == false)
{
- await invokeBeforeResponse(args);
+ await onBeforeResponse(args);
// send the response
await clientStreamWriter.WriteResponseAsync(args.HttpClient.Response,
@@ -166,10 +166,8 @@ await clientStreamWriter.WriteResponseAsync(args.HttpClient.Response,
// we need this to syphon out data from connection if API user changes them.
request.SetOriginalHeaders();
- args.TimeLine["Request Received"] = DateTime.Now;
-
// If user requested interception do it
- await invokeBeforeRequest(args);
+ await onBeforeRequest(args);
var response = args.HttpClient.Response;
@@ -286,7 +284,7 @@ await clientStreamWriter.WriteResponseAsync(args.HttpClient.Response,
}
finally
{
- await invokeAfterResponse(args);
+ await onAfterResponse(args);
args.Dispose();
}
}
@@ -410,8 +408,10 @@ private void prepareRequestHeaders(HeaderCollection requestHeaders)
///
/// The session event arguments.
///
- private async Task invokeBeforeRequest(SessionEventArgs args)
+ private async Task onBeforeRequest(SessionEventArgs args)
{
+ args.TimeLine["Request Received"] = DateTime.Now;
+
if (BeforeRequest != null)
{
await BeforeRequest.InvokeAsync(this, args, ExceptionFunc);
diff --git a/src/Titanium.Web.Proxy/ResponseHandler.cs b/src/Titanium.Web.Proxy/ResponseHandler.cs
index 8e8794730..cc181e081 100644
--- a/src/Titanium.Web.Proxy/ResponseHandler.cs
+++ b/src/Titanium.Web.Proxy/ResponseHandler.cs
@@ -58,7 +58,7 @@ private async Task handleHttpSessionResponse(SessionEventArgs args)
// if user requested call back then do it
if (!response.Locked)
{
- await invokeBeforeResponse(args);
+ await onBeforeResponse(args);
}
// it may changed in the user event
@@ -132,7 +132,7 @@ await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None,
///
///
///
- private async Task invokeBeforeResponse(SessionEventArgs args)
+ private async Task onBeforeResponse(SessionEventArgs args)
{
if (BeforeResponse != null)
{
@@ -145,7 +145,7 @@ private async Task invokeBeforeResponse(SessionEventArgs args)
///
///
///
- private async Task invokeAfterResponse(SessionEventArgs args)
+ private async Task onAfterResponse(SessionEventArgs args)
{
if (AfterResponse != null)
{
diff --git a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
index 3424aa405..8c08d81d9 100644
--- a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
+++ b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
@@ -19,19 +19,19 @@
- 4.5.0
+ 4.6.0
- 4.5.1
+ 4.6.0
- 4.5.0
+ 4.6.0
- 4.5.1
+ 4.6.0
diff --git a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
index 3424aa405..ad7709dd0 100644
--- a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+++ b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
@@ -1,7 +1,7 @@
- netstandard2.0;netcoreapp2.1
+ netstandard2.0;netstandard2.1;netcoreapp2.1
Titanium.Web.Proxy
false
True
@@ -19,19 +19,28 @@
- 4.5.0
+ 4.6.0
- 4.5.1
+ 4.6.0
+
+
+
+
+
+ 4.6.0
+
+
+ 4.6.0
- 4.5.0
+ 4.6.0
- 4.5.1
+ 4.6.0
diff --git a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
index d186b7440..35443b675 100644
--- a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
+++ b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
@@ -17,21 +17,29 @@
-
+
-
+
+
+
+
+
+
+
+
-
+
-
+
+
diff --git a/src/Titanium.Web.Proxy/WebSocketHandler.cs b/src/Titanium.Web.Proxy/WebSocketHandler.cs
index 4db29d790..628e65a5b 100644
--- a/src/Titanium.Web.Proxy/WebSocketHandler.cs
+++ b/src/Titanium.Web.Proxy/WebSocketHandler.cs
@@ -60,7 +60,7 @@ await clientStreamWriter.WriteResponseAsync(response,
// If user requested call back then do it
if (!args.HttpClient.Response.Locked)
{
- await invokeBeforeResponse(args);
+ await onBeforeResponse(args);
}
await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferPool,
diff --git a/tests/Titanium.Web.Proxy.IntegrationTests/Titanium.Web.Proxy.IntegrationTests.csproj b/tests/Titanium.Web.Proxy.IntegrationTests/Titanium.Web.Proxy.IntegrationTests.csproj
index 29f5b91bf..d0411b1dd 100644
--- a/tests/Titanium.Web.Proxy.IntegrationTests/Titanium.Web.Proxy.IntegrationTests.csproj
+++ b/tests/Titanium.Web.Proxy.IntegrationTests/Titanium.Web.Proxy.IntegrationTests.csproj
@@ -16,10 +16,10 @@
-
-
-
-
+
+
+
+
diff --git a/tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj b/tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
index 496f9d971..fd26bfc64 100644
--- a/tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
+++ b/tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
@@ -7,9 +7,9 @@
-
-
-
+
+
+