Commit 4c954df6 authored by Stéphane Graziano's avatar Stéphane Graziano

Optimisation : Rewrite startsWith with PeekBytesAsync instead of looping on PeekByteAsync

parent 9019ee91
...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy ...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy
TunnelConnectSessionEventArgs connectArgs = null; TunnelConnectSessionEventArgs connectArgs = null;
// Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if (await HttpHelper.IsConnectMethod(clientStream) == 1) if (await HttpHelper.IsConnectMethod(clientStream, cancellationToken) == 1)
{ {
// read the first line HTTP command // read the first line HTTP command
string httpCmd = await clientStream.ReadLineAsync(cancellationToken); string httpCmd = await clientStream.ReadLineAsync(cancellationToken);
......
using System; using System;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
...@@ -120,9 +122,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -120,9 +122,9 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param> /// <param name="clientStreamReader">The client stream reader.</param>
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader) internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader, CancellationToken cancellationToken = default(CancellationToken))
{ {
return startsWith(clientStreamReader, "CONNECT"); return startsWith(clientStreamReader, "CONNECT", cancellationToken);
} }
/// <summary> /// <summary>
...@@ -130,9 +132,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -130,9 +132,9 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param> /// <param name="clientStreamReader">The client stream reader.</param>
/// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader) internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader, CancellationToken cancellationToken = default(CancellationToken))
{ {
return startsWith(clientStreamReader, "PRI"); return startsWith(clientStreamReader, "PRI", cancellationToken);
} }
/// <summary> /// <summary>
...@@ -143,37 +145,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -143,37 +145,23 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns> /// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise /// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </returns> /// </returns>
private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, string expectedStart) private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, string expectedStart, CancellationToken cancellationToken = default(CancellationToken))
{ {
bool isExpected = true; int iRet = -1;
int lengthToCheck = 10; int lengthToCheck = 10;
for (int i = 0; i < lengthToCheck; i++)
{
int b = await clientStreamReader.PeekByteAsync(i);
if (b == -1)
{
return -1;
}
if (b == ' ' && i > 2) var vBuffer = await clientStreamReader.PeekBytesAsync(0, lengthToCheck, cancellationToken);
if (vBuffer != null)
{ {
return isExpected ? 1 : 0; var httpMethod = defaultEncoding.GetString(vBuffer);
}
char ch = (char)b; if (httpMethod.StartsWith(expectedStart))
if (!char.IsLetter(ch)) iRet = 1;
{ else if (Regex.Match(httpMethod, @"^[a-z]{3,} ", RegexOptions.IgnoreCase).Success) //valid HTTP requests start by at least 3 letters + space
return -1; iRet = 0;
}
if (i >= expectedStart.Length || ch != expectedStart[i])
{
isExpected = false;
}
} }
// only letters return iRet;
return isExpected ? 1 : 0;
} }
} }
} }
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