Commit 01e06028 authored by Honfika's avatar Honfika

Removed duplicate "copy chunked" method. Estension method added for ssl server name

parent e4435101
...@@ -62,7 +62,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -62,7 +62,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public MainWindow() public MainWindow()
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
//proxyServer.CertificateEngine = CertificateEngine.BouncyCastle; //proxyServer.CertificateEngine = CertificateEngine.DefaultWindows;
proxyServer.TrustRootCertificate = true; proxyServer.TrustRootCertificate = true;
proxyServer.CertificateManager.TrustRootCertificateAsAdministrator(); proxyServer.CertificateManager.TrustRootCertificateAsAdministrator();
proxyServer.ForwardToUpstreamGateway = true; proxyServer.ForwardToUpstreamGateway = true;
......
...@@ -5,7 +5,6 @@ using System.Net; ...@@ -5,7 +5,6 @@ using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.Decompression; using Titanium.Web.Proxy.Decompression;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses; using Titanium.Web.Proxy.Http.Responses;
...@@ -216,23 +215,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -216,23 +215,8 @@ namespace Titanium.Web.Proxy.EventArguments
//If chunked then its easy just read the whole body with the content length mentioned in the header //If chunked then its easy just read the whole body with the content length mentioned in the header
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol var writer = new HttpWriter(bodyStream, bufferSize);
if (isChunked) await writer.CopyBodyAsync(streamReader, isChunked, contentLength, true);
{
await streamReader.CopyBytesToStreamChunked(bodyStream);
}
else
{
//http 1.0
if (contentLength == -1)
{
contentLength = long.MaxValue;
}
//If not chunked then its easy just read the amount of bytes mentioned in content length header
await streamReader.CopyBytesToStream(bodyStream, contentLength);
}
return await GetDecompressedBody(contentEncoding, bodyStream.ToArray()); return await GetDecompressedBody(contentEncoding, bodyStream.ToArray());
} }
} }
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StreamExtended;
namespace Titanium.Web.Proxy.Extensions
{
static class SslExtensions
{
public static string GetServerName(this ClientHelloInfo clientHelloInfo)
{
if (clientHelloInfo.Extensions != null && clientHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension))
{
return serverNameExtension.Data;
}
return null;
}
}
}
...@@ -36,65 +36,5 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -36,65 +36,5 @@ namespace Titanium.Web.Proxy.Extensions
} }
} }
} }
/// <summary>
/// copies the specified bytes to the stream from the input stream
/// </summary>
/// <param name="streamReader"></param>
/// <param name="stream"></param>
/// <param name="totalBytesToRead"></param>
/// <returns></returns>
internal static async Task CopyBytesToStream(this CustomBinaryReader streamReader, Stream stream, long totalBytesToRead)
{
var buffer = streamReader.Buffer;
long remainingBytes = totalBytesToRead;
while (remainingBytes > 0)
{
int bytesToRead = buffer.Length;
if (remainingBytes < bytesToRead)
{
bytesToRead = (int)remainingBytes;
}
int bytesRead = await streamReader.ReadBytesAsync(buffer, bytesToRead);
if (bytesRead == 0)
{
break;
}
remainingBytes -= bytesRead;
await stream.WriteAsync(buffer, 0, bytesRead);
}
}
/// <summary>
/// Copies the stream chunked
/// </summary>
/// <param name="reader"></param>
/// <param name="stream"></param>
/// <returns></returns>
internal static async Task CopyBytesToStreamChunked(this CustomBinaryReader reader, Stream stream)
{
while (true)
{
string chunkHead = await reader.ReadLineAsync();
int chunkSize = int.Parse(chunkHead, NumberStyles.HexNumber);
if (chunkSize != 0)
{
await CopyBytesToStream(reader, stream, chunkSize);
}
//chunk trail
await reader.ReadLineAsync();
if (chunkSize == 0)
{
break;
}
}
}
} }
} }
...@@ -5,13 +5,12 @@ using System.Text; ...@@ -5,13 +5,12 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers; using StreamExtended.Helpers;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
abstract class HttpWriter internal class HttpWriter
{ {
public int BufferSize { get; } public int BufferSize { get; }
...@@ -23,7 +22,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -23,7 +22,7 @@ namespace Titanium.Web.Proxy.Helpers
private static readonly Encoder encoder = Encoding.ASCII.GetEncoder(); private static readonly Encoder encoder = Encoding.ASCII.GetEncoder();
protected HttpWriter(Stream stream, int bufferSize) internal HttpWriter(Stream stream, int bufferSize)
{ {
BufferSize = bufferSize; BufferSize = bufferSize;
...@@ -136,14 +135,16 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -136,14 +135,16 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="streamReader"></param> /// <param name="streamReader"></param>
/// <param name="isChunked"></param> /// <param name="isChunked"></param>
/// <param name="contentLength"></param> /// <param name="contentLength"></param>
/// <param name="removeChunkedEncoding"></param>
/// <returns></returns> /// <returns></returns>
internal Task CopyBodyAsync(CustomBinaryReader streamReader, bool isChunked, long contentLength) internal Task CopyBodyAsync(CustomBinaryReader streamReader, bool isChunked, long contentLength, bool removeChunkedEncoding)
{ {
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if (isChunked) if (isChunked)
{ {
//Need to revist, find any potential bugs //Need to revist, find any potential bugs
//send the body bytes to server in chunks //send the body bytes to server in chunks
return CopyBodyChunkedAsync(streamReader); return CopyBodyChunkedAsync(streamReader, removeChunkedEncoding);
} }
//http 1.0 //http 1.0
...@@ -152,6 +153,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -152,6 +153,7 @@ namespace Titanium.Web.Proxy.Helpers
contentLength = long.MaxValue; contentLength = long.MaxValue;
} }
//If not chunked then its easy just read the amount of bytes mentioned in content length header
return CopyBytesFromStream(streamReader, contentLength); return CopyBytesFromStream(streamReader, contentLength);
} }
...@@ -177,23 +179,29 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -177,23 +179,29 @@ namespace Titanium.Web.Proxy.Helpers
/// Copies the streams chunked /// Copies the streams chunked
/// </summary> /// </summary>
/// <param name="reader"></param> /// <param name="reader"></param>
/// <param name="removeChunkedEncoding"></param>
/// <returns></returns> /// <returns></returns>
private async Task CopyBodyChunkedAsync(CustomBinaryReader reader) private async Task CopyBodyChunkedAsync(CustomBinaryReader reader, bool removeChunkedEncoding)
{ {
while (true) while (true)
{ {
string chunkHead = await reader.ReadLineAsync(); string chunkHead = await reader.ReadLineAsync();
int chunkSize = int.Parse(chunkHead, NumberStyles.HexNumber); int chunkSize = int.Parse(chunkHead, NumberStyles.HexNumber);
if (!removeChunkedEncoding)
{
await WriteLineAsync(chunkHead); await WriteLineAsync(chunkHead);
}
if (chunkSize != 0) if (chunkSize != 0)
{ {
await CopyBytesFromStream(reader, chunkSize); await CopyBytesFromStream(reader, chunkSize);
} }
if (!removeChunkedEncoding)
{
await WriteLineAsync(); await WriteLineAsync();
}
//chunk trail //chunk trail
await reader.ReadLineAsync(); await reader.ReadLineAsync();
...@@ -205,9 +213,35 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -205,9 +213,35 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
private Task CopyBytesFromStream(CustomBinaryReader reader, long count) /// <summary>
/// Copies the specified bytes to the stream from the input stream
/// </summary>
/// <param name="reader"></param>
/// <param name="count"></param>
/// <returns></returns>
private async Task CopyBytesFromStream(CustomBinaryReader reader, long count)
{
var buffer = reader.Buffer;
long remainingBytes = count;
while (remainingBytes > 0)
{
int bytesToRead = buffer.Length;
if (remainingBytes < bytesToRead)
{
bytesToRead = (int)remainingBytes;
}
int bytesRead = await reader.ReadBytesAsync(buffer, bytesToRead);
if (bytesRead == 0)
{ {
return reader.CopyBytesToStream(stream, count); break;
}
remainingBytes -= bytesRead;
await stream.WriteAsync(buffer, 0, bytesRead);
}
} }
} }
} }
...@@ -226,18 +226,14 @@ namespace Titanium.Web.Proxy ...@@ -226,18 +226,14 @@ namespace Titanium.Web.Proxy
{ {
if (endPoint.EnableSsl) if (endPoint.EnableSsl)
{ {
var clientSslHelloInfo = await SslTools.PeekClientHello(clientStream); var clientHelloInfo = await SslTools.PeekClientHello(clientStream);
if (clientSslHelloInfo != null) if (clientHelloInfo != null)
{ {
var sslStream = new SslStream(clientStream); var sslStream = new SslStream(clientStream);
clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStream = new CustomBufferedStream(sslStream, BufferSize);
string sniHostName = null; string sniHostName = clientHelloInfo.GetServerName();
if (clientSslHelloInfo.Extensions != null && clientSslHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension))
{
sniHostName = serverNameExtension.Data;
}
string certName = HttpHelper.GetWildCardDomainName(sniHostName ?? endPoint.GenericCertificateName); string certName = HttpHelper.GetWildCardDomainName(sniHostName ?? endPoint.GenericCertificateName);
var certificate = CertificateManager.CreateCertificate(certName, false); var certificate = CertificateManager.CreateCertificate(certName, false);
...@@ -647,7 +643,7 @@ namespace Titanium.Web.Proxy ...@@ -647,7 +643,7 @@ namespace Titanium.Web.Proxy
else else
{ {
await args.WebSession.ServerConnection.StreamWriter.CopyBodyAsync(args.ProxyClient.ClientStreamReader, await args.WebSession.ServerConnection.StreamWriter.CopyBodyAsync(args.ProxyClient.ClientStreamReader,
request.IsChunked, request.ContentLength); request.IsChunked, request.ContentLength, false);
} }
} }
......
...@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy ...@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy
if (response.HasBody) if (response.HasBody)
{ {
await clientStreamWriter.CopyBodyAsync(args.WebSession.ServerConnection.StreamReader, await clientStreamWriter.CopyBodyAsync(args.WebSession.ServerConnection.StreamReader,
response.IsChunked, response.ContentLength); response.IsChunked, response.ContentLength, false);
} }
} }
} }
......
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