Commit 4b86cde8 authored by justcoding121's avatar justcoding121

asyncify more

parent ff0dddf4
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
...@@ -13,7 +14,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -13,7 +14,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
ProxyServer.BeforeRequest += OnRequest; ProxyServer.BeforeRequest += OnRequest;
ProxyServer.BeforeResponse += OnResponse; ProxyServer.BeforeResponse += OnResponse;
ProxyServer.RemoteCertificateValidationCallback += OnCertificateValidation; ProxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
//Exclude Https addresses you don't want to proxy //Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning //Usefull for clients that use certificate pinning
...@@ -61,9 +62,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -61,9 +62,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
ProxyServer.Stop(); ProxyServer.Stop();
} }
//Test On Request, intecept requests //intecept & cancel, redirect or update requests
//Read browser URL send back to proxy by the injection script in OnResponse event public async Task OnRequest(object sender, SessionEventArgs e)
public void OnRequest(object sender, SessionEventArgs e)
{ {
Console.WriteLine(e.WebSession.Request.Url); Console.WriteLine(e.WebSession.Request.Url);
...@@ -73,12 +73,12 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -73,12 +73,12 @@ namespace Titanium.Web.Proxy.Examples.Basic
if ((e.WebSession.Request.Method.ToUpper() == "POST" || e.WebSession.Request.Method.ToUpper() == "PUT")) if ((e.WebSession.Request.Method.ToUpper() == "POST" || e.WebSession.Request.Method.ToUpper() == "PUT"))
{ {
//Get/Set request body bytes //Get/Set request body bytes
byte[] bodyBytes = e.GetRequestBody(); byte[] bodyBytes = await e.GetRequestBody();
e.SetRequestBody(bodyBytes); await e.SetRequestBody(bodyBytes);
//Get/Set request body as string //Get/Set request body as string
string bodyString = e.GetRequestBodyAsString(); string bodyString = await e.GetRequestBodyAsString();
e.SetRequestBodyString(bodyString); await e.SetRequestBodyString(bodyString);
} }
...@@ -86,7 +86,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -86,7 +86,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Filter URL //Filter URL
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
{ {
e.Ok("<!DOCTYPE html>" + await e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" + "<html><body><h1>" +
"Website Blocked" + "Website Blocked" +
"</h1>" + "</h1>" +
...@@ -97,15 +97,13 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -97,15 +97,13 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Redirect example //Redirect example
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{ {
e.Redirect("https://www.paypal.com"); await e.Redirect("https://www.paypal.com");
} }
} }
//Test script injection //Modify response
//Insert script to read the Browser URL and send it back to proxy public async Task OnResponse(object sender, SessionEventArgs e)
public void OnResponse(object sender, SessionEventArgs e)
{ {
//read response headers //read response headers
var responseHeaders = e.WebSession.Response.ResponseHeaders; var responseHeaders = e.WebSession.Response.ResponseHeaders;
...@@ -116,11 +114,11 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -116,11 +114,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
if (e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html")) if (e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
{ {
byte[] bodyBytes = e.GetResponseBody(); byte[] bodyBytes = await e.GetResponseBody();
e.SetResponseBody(bodyBytes); await e.SetResponseBody(bodyBytes);
string body = e.GetResponseBodyAsString(); string body = await e.GetResponseBodyAsString();
e.SetResponseBodyString(body); await e.SetResponseBodyString(body);
} }
} }
} }
...@@ -131,13 +129,13 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -131,13 +129,13 @@ namespace Titanium.Web.Proxy.Examples.Basic
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
public void OnCertificateValidation(object sender, CertificateValidationEventArgs e) public async Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{ {
//set IsValid to true/false based on Certificate Errors //set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None) if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
e.IsValid = true; e.IsValid = true;
else else
e.Session.Ok("Cannot validate server certificate! Not safe to proceed."); await e.Session.Ok("Cannot validate server certificate! Not safe to proceed.");
} }
} }
} }
\ No newline at end of file
...@@ -34,7 +34,7 @@ Setup HTTP proxy: ...@@ -34,7 +34,7 @@ Setup HTTP proxy:
```csharp ```csharp
ProxyServer.BeforeRequest += OnRequest; ProxyServer.BeforeRequest += OnRequest;
ProxyServer.BeforeResponse += OnResponse; ProxyServer.BeforeResponse += OnResponse;
ProxyServer.RemoteCertificateValidationCallback += OnCertificateValidation; ProxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
//Exclude Https addresses you don't want to proxy //Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning //Usefull for clients that use certificate pinning
...@@ -62,7 +62,6 @@ Setup HTTP proxy: ...@@ -62,7 +62,6 @@ Setup HTTP proxy:
}; };
ProxyServer.AddEndPoint(transparentEndPoint); ProxyServer.AddEndPoint(transparentEndPoint);
//ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 }; //ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 }; //ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
...@@ -87,7 +86,8 @@ Sample request and response event handlers ...@@ -87,7 +86,8 @@ Sample request and response event handlers
```csharp ```csharp
public void OnRequest(object sender, SessionEventArgs e) //intecept & cancel, redirect or update requests
public async Task OnRequest(object sender, SessionEventArgs e)
{ {
Console.WriteLine(e.WebSession.Request.Url); Console.WriteLine(e.WebSession.Request.Url);
...@@ -97,12 +97,12 @@ Sample request and response event handlers ...@@ -97,12 +97,12 @@ Sample request and response event handlers
if ((e.WebSession.Request.Method.ToUpper() == "POST" || e.WebSession.Request.Method.ToUpper() == "PUT")) if ((e.WebSession.Request.Method.ToUpper() == "POST" || e.WebSession.Request.Method.ToUpper() == "PUT"))
{ {
//Get/Set request body bytes //Get/Set request body bytes
byte[] bodyBytes = e.GetRequestBody(); byte[] bodyBytes = await e.GetRequestBody();
e.SetRequestBody(bodyBytes); await e.SetRequestBody(bodyBytes);
//Get/Set request body as string //Get/Set request body as string
string bodyString = e.GetRequestBodyAsString(); string bodyString = await e.GetRequestBodyAsString();
e.SetRequestBodyString(bodyString); await e.SetRequestBodyString(bodyString);
} }
...@@ -110,7 +110,7 @@ Sample request and response event handlers ...@@ -110,7 +110,7 @@ Sample request and response event handlers
//Filter URL //Filter URL
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
{ {
e.Ok("<!DOCTYPE html>" + await e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" + "<html><body><h1>" +
"Website Blocked" + "Website Blocked" +
"</h1>" + "</h1>" +
...@@ -121,13 +121,13 @@ Sample request and response event handlers ...@@ -121,13 +121,13 @@ Sample request and response event handlers
//Redirect example //Redirect example
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{ {
e.Redirect("https://www.paypal.com"); await e.Redirect("https://www.paypal.com");
} }
} }
public void OnResponse(object sender, SessionEventArgs e) //Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{ {
//read response headers //read response headers
var responseHeaders = e.WebSession.Response.ResponseHeaders; var responseHeaders = e.WebSession.Response.ResponseHeaders;
...@@ -138,24 +138,28 @@ Sample request and response event handlers ...@@ -138,24 +138,28 @@ Sample request and response event handlers
{ {
if (e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html")) if (e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
{ {
byte[] bodyBytes = e.GetResponseBody(); byte[] bodyBytes = await e.GetResponseBody();
e.SetResponseBody(bodyBytes); await e.SetResponseBody(bodyBytes);
string body = e.GetResponseBodyAsString(); string body = await e.GetResponseBodyAsString();
e.SetResponseBodyString(body); await e.SetResponseBodyString(body);
} }
} }
} }
} }
// Allows overriding default certificate validation logic /// <summary>
public void OnCertificateValidation(object sender, CertificateValidationEventArgs e) /// Allows overriding default certificate validation logic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public async Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{ {
//set IsValid to true/false based on Certificate Errors //set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None) if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
e.IsValid = true; e.IsValid = true;
else else
e.Session.Ok("Cannot validate server certificate! Not safe to proceed."); await e.Session.Ok("Cannot validate server certificate! Not safe to proceed.");
} }
``` ```
Future roadmap Future roadmap
......
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
{ {
class DeflateCompression : ICompression class DeflateCompression : ICompression
{ {
public byte[] Compress(byte[] responseBody) public async Task<byte[]> Compress(byte[] responseBody)
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
using (var zip = new DeflateStream(ms, CompressionMode.Compress, true)) using (var zip = new DeflateStream(ms, CompressionMode.Compress, true))
{ {
zip.Write(responseBody, 0, responseBody.Length); await zip.WriteAsync(responseBody, 0, responseBody.Length).ConfigureAwait(false);
} }
return ms.ToArray(); return ms.ToArray();
......
using Ionic.Zlib; using Ionic.Zlib;
using System.IO; using System.IO;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
{ {
class GZipCompression : ICompression class GZipCompression : ICompression
{ {
public byte[] Compress(byte[] responseBody) public async Task<byte[]> Compress(byte[] responseBody)
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
using (var zip = new GZipStream(ms, CompressionMode.Compress, true)) using (var zip = new GZipStream(ms, CompressionMode.Compress, true))
{ {
zip.Write(responseBody, 0, responseBody.Length); await zip.WriteAsync(responseBody, 0, responseBody.Length).ConfigureAwait(false);
} }
return ms.ToArray(); return ms.ToArray();
......
namespace Titanium.Web.Proxy.Compression using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Compression
{ {
interface ICompression interface ICompression
{ {
byte[] Compress(byte[] responseBody); Task<byte[]> Compress(byte[] responseBody);
} }
} }
using Ionic.Zlib; using Ionic.Zlib;
using System.IO; using System.IO;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
{ {
class ZlibCompression : ICompression class ZlibCompression : ICompression
{ {
public byte[] Compress(byte[] responseBody) public async Task<byte[]> Compress(byte[] responseBody)
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
using (var zip = new ZlibStream(ms, CompressionMode.Compress, true)) using (var zip = new ZlibStream(ms, CompressionMode.Compress, true))
{ {
zip.Write(responseBody, 0, responseBody.Length); await zip.WriteAsync(responseBody, 0, responseBody.Length).ConfigureAwait(false);
} }
return ms.ToArray(); return ms.ToArray();
......
namespace Titanium.Web.Proxy.Decompression using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Decompression
{ {
class DefaultDecompression : IDecompression class DefaultDecompression : IDecompression
{ {
public byte[] Decompress(byte[] compressedArray) public Task<byte[]> Decompress(byte[] compressedArray)
{ {
return compressedArray; return Task.FromResult(compressedArray);
} }
} }
} }
using Ionic.Zlib; using Ionic.Zlib;
using System.IO; using System.IO;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
class DeflateDecompression : IDecompression class DeflateDecompression : IDecompression
{ {
public byte[] Decompress(byte[] compressedArray) public async Task<byte[]> Decompress(byte[] compressedArray)
{ {
var stream = new MemoryStream(compressedArray); var stream = new MemoryStream(compressedArray);
...@@ -17,9 +18,9 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -17,9 +18,9 @@ namespace Titanium.Web.Proxy.Decompression
using (var output = new MemoryStream()) using (var output = new MemoryStream())
{ {
int read; int read;
while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
{ {
output.Write(buffer, 0, read); await output.WriteAsync(buffer, 0, read).ConfigureAwait(false);
} }
return output.ToArray(); return output.ToArray();
......
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
class GZipDecompression : IDecompression class GZipDecompression : IDecompression
{ {
public byte[] Decompress(byte[] compressedArray) public async Task<byte[]> Decompress(byte[] compressedArray)
{ {
using (var decompressor = new GZipStream(new MemoryStream(compressedArray), CompressionMode.Decompress)) using (var decompressor = new GZipStream(new MemoryStream(compressedArray), CompressionMode.Decompress))
{ {
...@@ -14,9 +15,9 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -14,9 +15,9 @@ namespace Titanium.Web.Proxy.Decompression
using (var output = new MemoryStream()) using (var output = new MemoryStream())
{ {
int read; int read;
while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
{ {
output.Write(buffer, 0, read); await output.WriteAsync(buffer, 0, read).ConfigureAwait(false);
} }
return output.ToArray(); return output.ToArray();
} }
......
using System.IO; using System.IO;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
interface IDecompression interface IDecompression
{ {
byte[] Decompress(byte[] compressedArray); Task<byte[]> Decompress(byte[] compressedArray);
} }
} }
using Ionic.Zlib; using Ionic.Zlib;
using System.IO; using System.IO;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
class ZlibDecompression : IDecompression class ZlibDecompression : IDecompression
{ {
public byte[] Decompress(byte[] compressedArray) public async Task<byte[]> Decompress(byte[] compressedArray)
{ {
var memoryStream = new MemoryStream(compressedArray); var memoryStream = new MemoryStream(compressedArray);
using (var decompressor = new ZlibStream(memoryStream, CompressionMode.Decompress)) using (var decompressor = new ZlibStream(memoryStream, CompressionMode.Decompress))
...@@ -16,9 +17,9 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -16,9 +17,9 @@ namespace Titanium.Web.Proxy.Decompression
using (var output = new MemoryStream()) using (var output = new MemoryStream())
{ {
int read; int read;
while ((read = decompressor.Read(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
{ {
output.Write(buffer, 0, read); await output.WriteAsync(buffer, 0, read).ConfigureAwait(false);
} }
return output.ToArray(); return output.ToArray();
} }
......
...@@ -15,12 +15,12 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -15,12 +15,12 @@ namespace Titanium.Web.Proxy.Extensions
if (!string.IsNullOrEmpty(initialData)) if (!string.IsNullOrEmpty(initialData))
{ {
var bytes = Encoding.ASCII.GetBytes(initialData); var bytes = Encoding.ASCII.GetBytes(initialData);
output.Write(bytes, 0, bytes.Length); await output.WriteAsync(bytes, 0, bytes.Length);
} }
await input.CopyToAsync(output); await input.CopyToAsync(output);
} }
internal static void CopyBytesToStream(this CustomBinaryReader clientStreamReader, Stream stream, long totalBytesToRead) internal static async Task CopyBytesToStream(this CustomBinaryReader clientStreamReader, Stream stream, long totalBytesToRead)
{ {
var totalbytesRead = 0; var totalbytesRead = 0;
...@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy.Extensions
while (totalbytesRead < (int)totalBytesToRead) while (totalbytesRead < (int)totalBytesToRead)
{ {
var buffer = clientStreamReader.ReadBytes(bytesToRead); var buffer = await clientStreamReader.ReadBytesAsync(bytesToRead);
totalbytesRead += buffer.Length; totalbytesRead += buffer.Length;
var remainingBytes = (int)totalBytesToRead - totalbytesRead; var remainingBytes = (int)totalBytesToRead - totalbytesRead;
...@@ -43,26 +43,26 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -43,26 +43,26 @@ namespace Titanium.Web.Proxy.Extensions
{ {
bytesToRead = remainingBytes; bytesToRead = remainingBytes;
} }
stream.Write(buffer, 0, buffer.Length); await stream.WriteAsync(buffer, 0, buffer.Length);
} }
} }
internal static void CopyBytesToStreamChunked(this CustomBinaryReader clientStreamReader, Stream stream) internal static async Task CopyBytesToStreamChunked(this CustomBinaryReader clientStreamReader, Stream stream)
{ {
while (true) while (true)
{ {
var chuchkHead = clientStreamReader.ReadLine(); var chuchkHead = await clientStreamReader.ReadLineAsync();
var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber); var chunkSize = int.Parse(chuchkHead, NumberStyles.HexNumber);
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = clientStreamReader.ReadBytes(chunkSize); var buffer = await clientStreamReader.ReadBytesAsync(chunkSize);
stream.Write(buffer, 0, buffer.Length); await stream.WriteAsync(buffer, 0, buffer.Length);
//chunk trail //chunk trail
clientStreamReader.ReadLine(); await clientStreamReader.ReadLineAsync();
} }
else else
{ {
clientStreamReader.ReadLine(); await clientStreamReader.ReadLineAsync();
break; break;
} }
} }
......
...@@ -4,6 +4,7 @@ using System.IO; ...@@ -4,6 +4,7 @@ using System.IO;
using System.Net.Security; using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -31,7 +32,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -31,7 +32,7 @@ namespace Titanium.Web.Proxy.Helpers
/// Read a line from the byte stream /// Read a line from the byte stream
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal string ReadLine() internal async Task<string> ReadLineAsync()
{ {
var readBuffer = new StringBuilder(); var readBuffer = new StringBuilder();
...@@ -40,7 +41,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -40,7 +41,7 @@ namespace Titanium.Web.Proxy.Helpers
var lastChar = default(char); var lastChar = default(char);
var buffer = new byte[1]; var buffer = new byte[1];
while (this.stream.Read(buffer, 0, 1) > 0) while (await this.stream.ReadAsync(buffer, 0, 1).ConfigureAwait(false) > 0)
{ {
if (lastChar == '\r' && buffer[0] == '\n') if (lastChar == '\r' && buffer[0] == '\n')
{ {
...@@ -66,18 +67,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -66,18 +67,18 @@ namespace Titanium.Web.Proxy.Helpers
/// Read until the last new line /// Read until the last new line
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal List<string> ReadAllLines() internal async Task<List<string>> ReadAllLinesAsync()
{ {
string tmpLine; string tmpLine;
var requestLines = new List<string>(); var requestLines = new List<string>();
while (!string.IsNullOrEmpty(tmpLine = ReadLine())) while (!string.IsNullOrEmpty(tmpLine = await ReadLineAsync().ConfigureAwait(false)))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
return requestLines; return requestLines;
} }
internal byte[] ReadBytes(long totalBytesToRead) internal async Task<byte[]> ReadBytesAsync(long totalBytesToRead)
{ {
int bytesToRead = Constants.BUFFER_SIZE; int bytesToRead = Constants.BUFFER_SIZE;
...@@ -91,9 +92,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -91,9 +92,9 @@ namespace Titanium.Web.Proxy.Helpers
using (var outStream = new MemoryStream()) using (var outStream = new MemoryStream())
{ {
while ((bytesRead += this.stream.Read(buffer, 0, bytesToRead)) > 0) while ((bytesRead += await this.stream.ReadAsync(buffer, 0, bytesToRead).ConfigureAwait(false)) > 0)
{ {
outStream.Write(buffer, 0, bytesRead); await outStream.WriteAsync(buffer, 0, bytesRead).ConfigureAwait(false);
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
if (totalBytesRead == totalBytesToRead) if (totalBytesRead == totalBytesToRead)
......
...@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
public class TcpHelper public class TcpHelper
{ {
public static void SendRaw(Stream clientStream, string httpCmd, List<HttpHeader> requestHeaders, string hostName, public async static Task SendRaw(Stream clientStream, string httpCmd, List<HttpHeader> requestHeaders, string hostName,
int tunnelPort, bool isHttps) int tunnelPort, bool isHttps)
{ {
StringBuilder sb = null; StringBuilder sb = null;
...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Helpers
try try
{ {
sslStream = new SslStream(tunnelStream); sslStream = new SslStream(tunnelStream);
sslStream.AuthenticateAsClient(hostName, null, Constants.SupportedProtocols, false); await sslStream.AuthenticateAsClientAsync(hostName, null, Constants.SupportedProtocols, false);
tunnelStream = sslStream; tunnelStream = sslStream;
} }
catch catch
...@@ -62,17 +62,17 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -62,17 +62,17 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
var sendRelay = Task.Factory.StartNew(() => Task sendRelay;
{
if (sb != null) if (sb != null)
clientStream.CopyToAsync(sb.ToString(), tunnelStream).Wait(); sendRelay = clientStream.CopyToAsync(sb.ToString(), tunnelStream);
else else
clientStream.CopyToAsync(string.Empty, tunnelStream).Wait(); sendRelay = clientStream.CopyToAsync(string.Empty, tunnelStream);
});
var receiveRelay = Task.Factory.StartNew(() =>tunnelStream.CopyToAsync(string.Empty, clientStream).Wait()); var receiveRelay = tunnelStream.CopyToAsync(string.Empty, clientStream);
Task.WaitAll(sendRelay, receiveRelay); await Task.WhenAll(sendRelay, receiveRelay).ConfigureAwait(false);
} }
catch catch
{ {
......
...@@ -2,6 +2,7 @@ using System; ...@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -35,7 +36,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -35,7 +36,7 @@ namespace Titanium.Web.Proxy.Http
this.Response = new Response(); this.Response = new Response();
} }
internal void SendRequest() internal async Task SendRequest()
{ {
Stream stream = ProxyClient.Stream; Stream stream = ProxyClient.Stream;
...@@ -57,13 +58,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -57,13 +58,13 @@ namespace Titanium.Web.Proxy.Http
string request = requestLines.ToString(); string request = requestLines.ToString();
byte[] requestBytes = Encoding.ASCII.GetBytes(request); byte[] requestBytes = Encoding.ASCII.GetBytes(request);
stream.Write(requestBytes, 0, requestBytes.Length); await stream.WriteAsync(requestBytes, 0, requestBytes.Length);
stream.Flush(); stream.Flush();
if (ProxyServer.Enable100ContinueBehaviour) if (ProxyServer.Enable100ContinueBehaviour)
if (this.Request.ExpectContinue) if (this.Request.ExpectContinue)
{ {
var httpResult = ProxyClient.ServerStreamReader.ReadLine().Split(Constants.SpaceSplit, 3); var httpResult = (await ProxyClient.ServerStreamReader.ReadLineAsync()).Split(Constants.SpaceSplit, 3);
var responseStatusCode = httpResult[1].Trim(); var responseStatusCode = httpResult[1].Trim();
var responseStatusDescription = httpResult[2].Trim(); var responseStatusDescription = httpResult[2].Trim();
...@@ -72,27 +73,27 @@ namespace Titanium.Web.Proxy.Http ...@@ -72,27 +73,27 @@ namespace Titanium.Web.Proxy.Http
&& responseStatusDescription.ToLower().Equals("continue")) && responseStatusDescription.ToLower().Equals("continue"))
{ {
this.Request.Is100Continue = true; this.Request.Is100Continue = true;
ProxyClient.ServerStreamReader.ReadLine(); await ProxyClient.ServerStreamReader.ReadLineAsync();
} }
else if (responseStatusCode.Equals("417") else if (responseStatusCode.Equals("417")
&& responseStatusDescription.ToLower().Equals("expectation failed")) && responseStatusDescription.ToLower().Equals("expectation failed"))
{ {
this.Request.ExpectationFailed = true; this.Request.ExpectationFailed = true;
ProxyClient.ServerStreamReader.ReadLine(); await ProxyClient.ServerStreamReader.ReadLineAsync();
} }
} }
} }
internal void ReceiveResponse() internal async Task ReceiveResponse()
{ {
//return if this is already read //return if this is already read
if (this.Response.ResponseStatusCode != null) return; if (this.Response.ResponseStatusCode != null) return;
var httpResult = ProxyClient.ServerStreamReader.ReadLine().Split(Constants.SpaceSplit, 3); var httpResult = (await ProxyClient.ServerStreamReader.ReadLineAsync()).Split(Constants.SpaceSplit, 3);
if (string.IsNullOrEmpty(httpResult[0])) if (string.IsNullOrEmpty(httpResult[0]))
{ {
var s = ProxyClient.ServerStreamReader.ReadLine(); await ProxyClient.ServerStreamReader.ReadLineAsync();
} }
this.Response.HttpVersion = httpResult[0].Trim(); this.Response.HttpVersion = httpResult[0].Trim();
...@@ -105,8 +106,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -105,8 +106,8 @@ namespace Titanium.Web.Proxy.Http
{ {
this.Response.Is100Continue = true; this.Response.Is100Continue = true;
this.Response.ResponseStatusCode = null; this.Response.ResponseStatusCode = null;
ProxyClient.ServerStreamReader.ReadLine(); await ProxyClient.ServerStreamReader.ReadLineAsync();
ReceiveResponse(); await ReceiveResponse();
return; return;
} }
else if (this.Response.ResponseStatusCode.Equals("417") else if (this.Response.ResponseStatusCode.Equals("417")
...@@ -114,12 +115,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -114,12 +115,12 @@ namespace Titanium.Web.Proxy.Http
{ {
this.Response.ExpectationFailed = true; this.Response.ExpectationFailed = true;
this.Response.ResponseStatusCode = null; this.Response.ResponseStatusCode = null;
ProxyClient.ServerStreamReader.ReadLine(); await ProxyClient.ServerStreamReader.ReadLineAsync();
ReceiveResponse(); await ReceiveResponse();
return; return;
} }
List<string> responseLines = ProxyClient.ServerStreamReader.ReadAllLines(); List<string> responseLines = await ProxyClient.ServerStreamReader.ReadAllLinesAsync();
for (int index = 0; index < responseLines.Count; ++index) for (int index = 0; index < responseLines.Count; ++index)
{ {
......
...@@ -61,13 +61,15 @@ namespace Titanium.Web.Proxy.Network ...@@ -61,13 +61,15 @@ namespace Titanium.Web.Proxy.Network
} }
if (cached == null) if (cached == null)
cached = await CreateClient(sessionArgs,hostname, port, isSecure, version); cached = await CreateClient(sessionArgs, hostname, port, isSecure, version).ConfigureAwait(false);
//if (ConnectionCache.Where(x => x.HostName == hostname && x.port == port && //just create one more preemptively
//x.IsSecure == isSecure && x.TcpClient.Connected && x.Version.Equals(version)).Count() < 2) if (ConnectionCache.Where(x => x.HostName == hostname && x.port == port &&
//{ x.IsSecure == isSecure && x.TcpClient.Connected && x.Version.Equals(version)).Count() < 2)
// Task.Factory.StartNew(() => CreateClient(sessionArgs, hostname, port, isSecure, version)); {
//} var task = CreateClient(sessionArgs, hostname, port, isSecure, version)
.ContinueWith(x => ReleaseClient(x.Result));
}
return cached; return cached;
} }
...@@ -81,12 +83,12 @@ namespace Titanium.Web.Proxy.Network ...@@ -81,12 +83,12 @@ namespace Titanium.Web.Proxy.Network
{ {
CustomSslStream sslStream = null; CustomSslStream sslStream = null;
if(ProxyServer.UpStreamHttpsProxy!=null) if (ProxyServer.UpStreamHttpsProxy != null)
{ {
client = new TcpClient(ProxyServer.UpStreamHttpsProxy.HostName, ProxyServer.UpStreamHttpsProxy.Port); client = new TcpClient(ProxyServer.UpStreamHttpsProxy.HostName, ProxyServer.UpStreamHttpsProxy.Port);
stream = (Stream)client.GetStream(); stream = (Stream)client.GetStream();
var writer = new StreamWriter(stream,Encoding.ASCII, Constants.BUFFER_SIZE, true); var writer = new StreamWriter(stream, Encoding.ASCII, Constants.BUFFER_SIZE, true);
writer.WriteLine(string.Format("CONNECT {0}:{1} {2}", sessionArgs.WebSession.Request.RequestUri.Host, sessionArgs.WebSession.Request.RequestUri.Port, sessionArgs.WebSession.Request.HttpVersion)); writer.WriteLine(string.Format("CONNECT {0}:{1} {2}", sessionArgs.WebSession.Request.RequestUri.Host, sessionArgs.WebSession.Request.RequestUri.Port, sessionArgs.WebSession.Request.HttpVersion));
writer.WriteLine(string.Format("Host: {0}:{1}", sessionArgs.WebSession.Request.RequestUri.Host, sessionArgs.WebSession.Request.RequestUri.Port)); writer.WriteLine(string.Format("Host: {0}:{1}", sessionArgs.WebSession.Request.RequestUri.Host, sessionArgs.WebSession.Request.RequestUri.Port));
...@@ -95,12 +97,12 @@ namespace Titanium.Web.Proxy.Network ...@@ -95,12 +97,12 @@ namespace Titanium.Web.Proxy.Network
writer.Flush(); writer.Flush();
var reader = new CustomBinaryReader(stream); var reader = new CustomBinaryReader(stream);
var result = reader.ReadLine(); var result = await reader.ReadLineAsync().ConfigureAwait(false);
if (!result.ToLower().Contains("200 connection established")) if (!result.ToLower().Contains("200 connection established"))
throw new Exception("Upstream proxy failed to create a secure tunnel"); throw new Exception("Upstream proxy failed to create a secure tunnel");
reader.ReadAllLines(); await reader.ReadAllLinesAsync().ConfigureAwait(false);
} }
else else
{ {
...@@ -110,9 +112,9 @@ namespace Titanium.Web.Proxy.Network ...@@ -110,9 +112,9 @@ namespace Titanium.Web.Proxy.Network
try try
{ {
sslStream = new CustomSslStream(stream, true, ProxyServer.ValidateServerCertificate); sslStream = new CustomSslStream(stream, true, new RemoteCertificateValidationCallback(ProxyServer.ValidateServerCertificate));
sslStream.Session = sessionArgs; sslStream.Session = sessionArgs;
await sslStream.AuthenticateAsClientAsync(hostname, null, Constants.SupportedProtocols, false); await sslStream.AuthenticateAsClientAsync(hostname, null, Constants.SupportedProtocols, false).ConfigureAwait(false);
stream = (Stream)sslStream; stream = (Stream)sslStream;
} }
catch catch
...@@ -155,7 +157,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -155,7 +157,7 @@ namespace Titanium.Web.Proxy.Network
ConnectionCache.Add(Connection); ConnectionCache.Add(Connection);
} }
internal static void ClearIdleConnections() internal async static void ClearIdleConnections()
{ {
while (true) while (true)
{ {
...@@ -171,7 +173,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -171,7 +173,7 @@ namespace Titanium.Web.Proxy.Network
ConnectionCache.RemoveAll(x => x.LastAccess < cutOff); ConnectionCache.RemoveAll(x => x.LastAccess < cutOff);
} }
Thread.Sleep(1000 * 60 * 3); await Task.Delay(1000 * 60 * 3).ConfigureAwait(false);
} }
} }
......
...@@ -34,8 +34,8 @@ namespace Titanium.Web.Proxy ...@@ -34,8 +34,8 @@ namespace Titanium.Web.Proxy
public static string RootCertificateName { get; set; } public static string RootCertificateName { get; set; }
public static bool Enable100ContinueBehaviour { get; set; } public static bool Enable100ContinueBehaviour { get; set; }
public static event EventHandler<SessionEventArgs> BeforeRequest; public static event Func<object, SessionEventArgs, Task> BeforeRequest;
public static event EventHandler<SessionEventArgs> BeforeResponse; public static event Func<object, SessionEventArgs, Task> BeforeResponse;
/// <summary> /// <summary>
/// External proxy for Http /// External proxy for Http
...@@ -50,14 +50,14 @@ namespace Titanium.Web.Proxy ...@@ -50,14 +50,14 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication /// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary> /// </summary>
public static event EventHandler<CertificateValidationEventArgs> RemoteCertificateValidationCallback; public static event Func<object, CertificateValidationEventArgs, Task> ServerCertificateValidationCallback;
public static List<ProxyEndPoint> ProxyEndPoints { get; set; } public static List<ProxyEndPoint> ProxyEndPoints { get; set; }
public static void Initialize() public static void Initialize()
{ {
Task.Factory.StartNew(() => TcpConnectionManager.ClearIdleConnections()); TcpConnectionManager.ClearIdleConnections();
} }
public static void AddEndPoint(ProxyEndPoint endPoint) public static void AddEndPoint(ProxyEndPoint endPoint)
...@@ -236,50 +236,5 @@ namespace Titanium.Web.Proxy ...@@ -236,50 +236,5 @@ namespace Titanium.Web.Proxy
} }
/// <summary>
/// Call back to override server certificate validation
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
internal static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
var param = sender as CustomSslStream;
if (RemoteCertificateValidationCallback != null)
{
var args = new CertificateValidationEventArgs();
args.Session = param.Session;
args.Certificate = certificate;
args.Chain = chain;
args.SslPolicyErrors = sslPolicyErrors;
RemoteCertificateValidationCallback.Invoke(null, args);
if(!args.IsValid)
{
param.Session.WebSession.Request.CancelRequest = true;
}
return args.IsValid;
}
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
//By default
//do not allow this client to communicate with unauthenticated servers.
return false;
}
} }
} }
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
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