From a991c2bc4a307ff85cfab95a8191d539e81dc6ee Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 30 Apr 2018 17:25:28 +0200 Subject: [PATCH 01/23] simplify custom stream --- .gitignore | 2 +- .../Titanium.Web.Proxy.Examples.Wpf.csproj | 4 +- .../packages.config | 2 +- .../EventArguments/DataEventArgs.cs | 32 ------- .../EventArguments/LimitedStream.cs | 14 ++- .../EventArguments/SessionEventArgs.cs | 26 ++---- .../EventArguments/SessionEventArgsBase.cs | 3 +- Titanium.Web.Proxy/ExplicitClientHandler.cs | 20 ++-- Titanium.Web.Proxy/Helpers/HttpWriter.cs | 93 +++++++++++++------ Titanium.Web.Proxy/Http/HeaderParser.cs | 2 +- Titanium.Web.Proxy/Http/HttpWebClient.cs | 16 ++-- .../Network/DebugCustomBufferedStream.cs | 4 +- Titanium.Web.Proxy/Network/ProxyClient.cs | 5 - .../Network/Tcp/TcpConnection.cs | 7 -- .../Network/Tcp/TcpConnectionFactory.cs | 20 ++-- Titanium.Web.Proxy/RequestHandler.cs | 13 +-- .../Titanium.Web.Proxy.Docs.csproj | 4 +- Titanium.Web.Proxy/Titanium.Web.Proxy.csproj | 2 +- Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec | 2 +- .../TransparentClientHandler.cs | 8 +- Titanium.Web.Proxy/packages.config | 2 +- 21 files changed, 125 insertions(+), 156 deletions(-) delete mode 100644 Titanium.Web.Proxy/EventArguments/DataEventArgs.cs diff --git a/.gitignore b/.gitignore index 71488d2de..c2715dea6 100644 --- a/.gitignore +++ b/.gitignore @@ -205,4 +205,4 @@ FakesAssemblies/ *.opt # Docfx -docs/manifest.json \ No newline at end of file +docs/manifest.json 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 b226576e3..0e6284a64 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 @@ -51,8 +51,8 @@ 4 - - ..\..\packages\StreamExtended.1.0.147-beta\lib\net45\StreamExtended.dll + + ..\..\packages\StreamExtended.1.0.160-beta\lib\net45\StreamExtended.dll diff --git a/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config b/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config index 23dc8ff78..89e1575a6 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config +++ b/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/Titanium.Web.Proxy/EventArguments/DataEventArgs.cs b/Titanium.Web.Proxy/EventArguments/DataEventArgs.cs deleted file mode 100644 index df7cc1bbd..000000000 --- a/Titanium.Web.Proxy/EventArguments/DataEventArgs.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; - -namespace Titanium.Web.Proxy.EventArguments -{ - /// - /// Wraps the data sent/received by a proxy server instance. - /// - public class DataEventArgs : EventArgs - { - internal DataEventArgs(byte[] buffer, int offset, int count) - { - Buffer = buffer; - Offset = offset; - Count = count; - } - - /// - /// The buffer with data. - /// - public byte[] Buffer { get; } - - /// - /// Offset in buffer from which valid data begins. - /// - public int Offset { get; } - - /// - /// Length from offset in buffer with valid data. - /// - public int Count { get; } - } -} diff --git a/Titanium.Web.Proxy/EventArguments/LimitedStream.cs b/Titanium.Web.Proxy/EventArguments/LimitedStream.cs index ebe372d62..3735bbdf5 100644 --- a/Titanium.Web.Proxy/EventArguments/LimitedStream.cs +++ b/Titanium.Web.Proxy/EventArguments/LimitedStream.cs @@ -9,18 +9,16 @@ namespace Titanium.Web.Proxy.EventArguments { internal class LimitedStream : Stream { - private readonly CustomBinaryReader baseReader; - private readonly CustomBufferedStream baseStream; + private readonly ICustomStreamReader baseStream; private readonly bool isChunked; private long bytesRemaining; private bool readChunkTrail; - internal LimitedStream(CustomBufferedStream baseStream, CustomBinaryReader baseReader, bool isChunked, + internal LimitedStream(ICustomStreamReader baseStream, bool isChunked, long contentLength) { this.baseStream = baseStream; - this.baseReader = baseReader; this.isChunked = isChunked; bytesRemaining = isChunked ? 0 @@ -48,12 +46,12 @@ private void GetNextChunk() if (readChunkTrail) { // read the chunk trail of the previous chunk - string s = baseReader.ReadLineAsync().Result; + string s = baseStream.ReadLineAsync().Result; } readChunkTrail = true; - string chunkHead = baseReader.ReadLineAsync().Result; + string chunkHead = baseStream.ReadLineAsync().Result; int idx = chunkHead.IndexOf(";", StringComparison.Ordinal); if (idx >= 0) { @@ -68,7 +66,7 @@ private void GetNextChunk() bytesRemaining = -1; //chunk trail - baseReader.ReadLineAsync().Wait(); + baseStream.ReadLineAsync().Wait(); } } @@ -127,7 +125,7 @@ public async Task Finish() { if (bytesRemaining != -1) { - var buffer = BufferPool.GetBuffer(baseReader.Buffer.Length); + var buffer = BufferPool.GetBuffer(baseStream.BufferSize); try { int res = await ReadAsync(buffer, 0, buffer.Length); diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs index f58ecf366..d4508d9da 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs @@ -68,16 +68,11 @@ public bool ReRequest /// public event EventHandler MultipartRequestPartSent; - private CustomBufferedStream GetStream(bool isRequest) + private ICustomStreamReader GetStreamReader(bool isRequest) { return isRequest ? ProxyClient.ClientStream : WebSession.ServerConnection.Stream; } - private CustomBinaryReader GetStreamReader(bool isRequest) - { - return isRequest ? ProxyClient.ClientStreamReader : WebSession.ServerConnection.StreamReader; - } - private HttpWriter GetStreamWriter(bool isRequest) { return isRequest ? (HttpWriter)ProxyClient.ClientStreamWriter : WebSession.ServerConnection.StreamWriter; @@ -207,11 +202,10 @@ internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode t string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType); using (var copyStream = new CopyStream(reader, writer, BufferSize)) - using (var copyStreamReader = new CustomBinaryReader(copyStream, BufferSize)) { while (contentLength > copyStream.ReadBytes) { - long read = await ReadUntilBoundaryAsync(copyStreamReader, contentLength, boundary, cancellationToken); + long read = await ReadUntilBoundaryAsync(copyStream, contentLength, boundary, cancellationToken); if (read == 0) { break; @@ -220,7 +214,7 @@ internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode t if (contentLength > copyStream.ReadBytes) { var headers = new HeaderCollection(); - await HeaderParser.ReadHeaders(copyStreamReader, headers, cancellationToken); + await HeaderParser.ReadHeaders(copyStream, headers, cancellationToken); OnMultipartRequestPartSent(boundary, headers); } } @@ -241,8 +235,7 @@ internal async Task CopyResponseBodyAsync(HttpWriter writer, TransformationMode private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, TransformationMode transformation, Action onCopy, CancellationToken cancellationToken) { - var stream = GetStream(isRequest); - var reader = GetStreamReader(isRequest); + var stream = GetStreamReader(isRequest); var requestResponse = isRequest ? (RequestResponseBase)WebSession.Request : WebSession.Response; @@ -250,7 +243,7 @@ private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, Transformati long contentLength = requestResponse.ContentLength; if (transformation == TransformationMode.None) { - await writer.CopyBodyAsync(reader, isChunked, contentLength, onCopy, cancellationToken); + await writer.CopyBodyAsync(stream, isChunked, contentLength, onCopy, cancellationToken); return; } @@ -259,7 +252,7 @@ private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, Transformati string contentEncoding = requestResponse.ContentEncoding; - Stream s = limitedStream = new LimitedStream(stream, reader, isChunked, contentLength); + Stream s = limitedStream = new LimitedStream(stream, isChunked, contentLength); if (transformation == TransformationMode.Uncompress && contentEncoding != null) { @@ -269,13 +262,10 @@ private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, Transformati try { var bufStream = new CustomBufferedStream(s, BufferSize, true); - reader = new CustomBinaryReader(bufStream, BufferSize); - - await writer.CopyBodyAsync(reader, false, -1, onCopy, cancellationToken); + await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken); } finally { - reader?.Dispose(); decompressStream?.Dispose(); await limitedStream.Finish(); @@ -287,7 +277,7 @@ private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, Transformati /// Read a line from the byte stream /// /// - private async Task ReadUntilBoundaryAsync(CustomBinaryReader reader, long totalBytesToRead, string boundary, CancellationToken cancellationToken) + private async Task ReadUntilBoundaryAsync(ICustomStreamReader reader, long totalBytesToRead, string boundary, CancellationToken cancellationToken) { int bufferDataLength = 0; diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index dd5fdd1a1..98ac1e355 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -1,6 +1,7 @@ using System; using System.Net; using System.Threading; +using StreamExtended.Network; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Models; @@ -50,7 +51,7 @@ protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, { if (RunTime.IsWindows) { - var remoteEndPoint = (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint; + var remoteEndPoint = ClientEndPoint; //If client is localhost get the process id if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index 176882455..ff5d828ec 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -34,7 +34,6 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); - var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); try @@ -46,7 +45,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli if (await HttpHelper.IsConnectMethod(clientStream) == 1) { //read the first line HTTP command - string httpCmd = await clientStreamReader.ReadLineAsync(cancellationToken); + string httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (string.IsNullOrEmpty(httpCmd)) { return; @@ -64,7 +63,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli HttpVersion = version }; - await HeaderParser.ReadHeaders(clientStreamReader, connectRequest.Headers, cancellationToken); + await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken); connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest, cancellationTokenSource, ExceptionFunc); @@ -159,7 +158,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, options.ApplicationProtocols = clientHelloInfo.GetAlpn(); if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0) { - options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList; + options.ApplicationProtocols = Titanium.Web.Proxy.Extensions.SslExtensions.Http11ProtocolAsList; } } @@ -172,8 +171,6 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, //HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); - clientStreamReader.Dispose(); - clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); } catch (Exception e) @@ -240,23 +237,23 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream) == 1) { // todo - string httpCmd = await clientStreamReader.ReadLineAsync(cancellationToken); + string httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (httpCmd == "PRI * HTTP/2.0") { // HTTP/2 Connection Preface - string line = await clientStreamReader.ReadLineAsync(cancellationToken); + string line = await clientStream.ReadLineAsync(cancellationToken); if (line != string.Empty) { throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); } - line = await clientStreamReader.ReadLineAsync(cancellationToken); + line = await clientStream.ReadLineAsync(cancellationToken); if (line != "SM") { throw new Exception($"HTTP/2 Protocol violation. 'SM' expected, '{line}' received"); } - line = await clientStreamReader.ReadLineAsync(cancellationToken); + line = await clientStream.ReadLineAsync(cancellationToken); if (line != string.Empty) { throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); @@ -279,7 +276,7 @@ await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, } //Now create the request - await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamReader, + await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamWriter, cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); } @@ -301,7 +298,6 @@ await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamRe } finally { - clientStreamReader.Dispose(); clientStream.Dispose(); if (!cancellationTokenSource.IsCancellationRequested) { diff --git a/Titanium.Web.Proxy/Helpers/HttpWriter.cs b/Titanium.Web.Proxy/Helpers/HttpWriter.cs index d9810ff60..0938658a5 100644 --- a/Titanium.Web.Proxy/Helpers/HttpWriter.cs +++ b/Titanium.Web.Proxy/Helpers/HttpWriter.cs @@ -11,17 +11,20 @@ namespace Titanium.Web.Proxy.Helpers { - internal class HttpWriter : CustomBinaryWriter + internal class HttpWriter : ICustomStreamWriter { + private readonly Stream stream; + private static readonly byte[] newLine = ProxyConstants.NewLine; private static readonly Encoder encoder = Encoding.ASCII.GetEncoder(); private readonly char[] charBuffer; - internal HttpWriter(Stream stream, int bufferSize) : base(stream) + internal HttpWriter(Stream stream, int bufferSize) { BufferSize = bufferSize; + this.stream = stream; // ASCII encoder max byte count is char count + 1 charBuffer = new char[BufferSize - 1]; @@ -62,7 +65,7 @@ private Task WriteAsyncInternal(string value, bool addNewLine, CancellationToken idx += newLineChars; } - return WriteAsync(buffer, 0, idx, cancellationToken); + return stream.WriteAsync(buffer, 0, idx, cancellationToken); } finally { @@ -82,7 +85,7 @@ private Task WriteAsyncInternal(string value, bool addNewLine, CancellationToken idx += newLineChars; } - return WriteAsync(buffer, 0, idx, cancellationToken); + return stream.WriteAsync(buffer, 0, idx, cancellationToken); } } @@ -109,26 +112,26 @@ internal async Task WriteHeadersAsync(HeaderCollection headers, bool flush = tru await WriteLineAsync(cancellationToken); if (flush) { - await FlushAsync(cancellationToken); + await stream.FlushAsync(cancellationToken); } } internal async Task WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default) { - await WriteAsync(data, 0, data.Length, cancellationToken); + await stream.WriteAsync(data, 0, data.Length, cancellationToken); if (flush) { - await FlushAsync(cancellationToken); + await stream.FlushAsync(cancellationToken); } } internal async Task WriteAsync(byte[] data, int offset, int count, bool flush, CancellationToken cancellationToken = default) { - await WriteAsync(data, offset, count, cancellationToken); + await stream.WriteAsync(data, offset, count, cancellationToken); if (flush) { - await FlushAsync(cancellationToken); + await stream.FlushAsync(cancellationToken); } } @@ -159,7 +162,7 @@ internal Task WriteBodyAsync(byte[] data, bool isChunked, CancellationToken canc /// /// /// - internal Task CopyBodyAsync(CustomBinaryReader streamReader, bool isChunked, long contentLength, + internal Task CopyBodyAsync(ICustomStreamReader streamReader, bool isChunked, long contentLength, Action onCopy, CancellationToken cancellationToken) { //For chunked request we need to read data as they arrive, until we reach a chunk end symbol @@ -204,7 +207,7 @@ private async Task WriteBodyChunkedAsync(byte[] data, CancellationToken cancella /// /// /// - private async Task CopyBodyChunkedAsync(CustomBinaryReader reader, Action onCopy, + private async Task CopyBodyChunkedAsync(ICustomStreamReader reader, Action onCopy, CancellationToken cancellationToken) { while (true) @@ -245,31 +248,39 @@ private async Task CopyBodyChunkedAsync(CustomBinaryReader reader, Action /// /// - private async Task CopyBytesFromStream(CustomBinaryReader reader, long count, Action onCopy, + private async Task CopyBytesFromStream(ICustomStreamReader reader, long count, Action onCopy, CancellationToken cancellationToken) { - var buffer = reader.Buffer; - long remainingBytes = count; + var buffer = BufferPool.GetBuffer(BufferSize); - while (remainingBytes > 0) + try { - int bytesToRead = buffer.Length; - if (remainingBytes < bytesToRead) - { - bytesToRead = (int)remainingBytes; - } + long remainingBytes = count; - int bytesRead = await reader.ReadBytesAsync(buffer, bytesToRead, cancellationToken); - if (bytesRead == 0) + while (remainingBytes > 0) { - break; - } + int bytesToRead = buffer.Length; + if (remainingBytes < bytesToRead) + { + bytesToRead = (int)remainingBytes; + } - remainingBytes -= bytesRead; + int bytesRead = await reader.ReadAsync(buffer, 0, bytesToRead, cancellationToken); + if (bytesRead == 0) + { + break; + } - await WriteAsync(buffer, 0, bytesRead, cancellationToken); + remainingBytes -= bytesRead; - onCopy?.Invoke(buffer, 0, bytesRead); + await stream.WriteAsync(buffer, 0, bytesRead, cancellationToken); + + onCopy?.Invoke(buffer, 0, bytesRead); + } + } + finally + { + BufferPool.ReturnBuffer(buffer); } } @@ -291,5 +302,33 @@ protected async Task WriteAsync(RequestResponseBase requestResponse, bool flush await WriteBodyAsync(body, requestResponse.IsChunked, cancellationToken); } } + + /// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// The sum of offset and count is greater than the buffer length. + /// buffer is null. + /// offset or count is negative. + /// An I/O error occured, such as the specified file cannot be found. + /// The stream does not support writing. + /// was called after the stream was closed. + public void Write(byte[] buffer, int offset, int count) + { + stream.Write(buffer, offset, count); + } + + /// + /// Asynchronously writes a sequence of bytes to the current stream, advances the current position within this stream by the number of bytes written, and monitors cancellation requests. + /// + /// The buffer to write data from. + /// The zero-based byte offset in from which to begin copying bytes to the stream. + /// The maximum number of bytes to write. + /// The token to monitor for cancellation requests. The default value is . + /// A task that represents the asynchronous write operation. + public Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return stream.WriteAsync(buffer, offset, count, cancellationToken); + } } } diff --git a/Titanium.Web.Proxy/Http/HeaderParser.cs b/Titanium.Web.Proxy/Http/HeaderParser.cs index 45a65c5f5..c28ec4292 100644 --- a/Titanium.Web.Proxy/Http/HeaderParser.cs +++ b/Titanium.Web.Proxy/Http/HeaderParser.cs @@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Http { internal static class HeaderParser { - internal static async Task ReadHeaders(CustomBinaryReader reader, HeaderCollection headerCollection, + internal static async Task ReadHeaders(ICustomStreamReader reader, HeaderCollection headerCollection, CancellationToken cancellationToken) { string tmpLine; diff --git a/Titanium.Web.Proxy/Http/HttpWebClient.cs b/Titanium.Web.Proxy/Http/HttpWebClient.cs index f7c582598..bb92dee81 100644 --- a/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -121,7 +121,7 @@ await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamPro { if (Request.ExpectContinue) { - string httpStatus = await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + string httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken); Response.ParseResponseLine(httpStatus, out _, out int responseStatusCode, out string responseStatusDescription); @@ -131,13 +131,13 @@ await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamPro && responseStatusDescription.EqualsIgnoreCase("continue")) { Request.Is100Continue = true; - await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + await ServerConnection.Stream.ReadLineAsync(cancellationToken); } else if (responseStatusCode == (int)HttpStatusCode.ExpectationFailed && responseStatusDescription.EqualsIgnoreCase("expectation failed")) { Request.ExpectationFailed = true; - await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + await ServerConnection.Stream.ReadLineAsync(cancellationToken); } } } @@ -155,7 +155,7 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) return; } - string httpStatus = await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + string httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken); if (httpStatus == null) { throw new IOException(); @@ -163,7 +163,7 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) if (httpStatus == string.Empty) { - httpStatus = await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken); } Response.ParseResponseLine(httpStatus, out var version, out int statusCode, out string statusDescription); @@ -179,7 +179,7 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) //Read the next line after 100-continue Response.Is100Continue = true; Response.StatusCode = 0; - await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + await ServerConnection.Stream.ReadLineAsync(cancellationToken); //now receive response await ReceiveResponse(cancellationToken); @@ -192,7 +192,7 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) //read next line after expectation failed response Response.ExpectationFailed = true; Response.StatusCode = 0; - await ServerConnection.StreamReader.ReadLineAsync(cancellationToken); + await ServerConnection.Stream.ReadLineAsync(cancellationToken); //now receive response await ReceiveResponse(cancellationToken); @@ -200,7 +200,7 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) } //Read the response headers in to unique and non-unique header collections - await HeaderParser.ReadHeaders(ServerConnection.StreamReader, Response.Headers, cancellationToken); + await HeaderParser.ReadHeaders(ServerConnection.Stream, Response.Headers, cancellationToken); } /// diff --git a/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs b/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs index 8d99002ac..92698ac04 100644 --- a/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs +++ b/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs @@ -24,12 +24,12 @@ public DebugCustomBufferedStream(Stream baseStream, int bufferSize) : base(baseS public int Counter { get; } - protected override void OnDataSent(byte[] buffer, int offset, int count) + protected override void OnDataWrite(byte[] buffer, int offset, int count) { fileStreamSent.Write(buffer, offset, count); } - protected override void OnDataReceived(byte[] buffer, int offset, int count) + protected override void OnDataRead(byte[] buffer, int offset, int count) { fileStreamReceived.Write(buffer, offset, count); } diff --git a/Titanium.Web.Proxy/Network/ProxyClient.cs b/Titanium.Web.Proxy/Network/ProxyClient.cs index 611576a12..7e1e387ea 100644 --- a/Titanium.Web.Proxy/Network/ProxyClient.cs +++ b/Titanium.Web.Proxy/Network/ProxyClient.cs @@ -19,11 +19,6 @@ internal class ProxyClient /// internal CustomBufferedStream ClientStream { get; set; } - /// - /// Used to read line by line from client - /// - internal CustomBinaryReader ClientStreamReader { get; set; } - /// /// Used to write line by line to client /// diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs b/Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs index c68fd2a57..5a5048346 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs @@ -46,11 +46,6 @@ internal TcpConnection(ProxyServer proxyServer) internal TcpClient TcpClient { private get; set; } - /// - /// Used to read lines from server - /// - internal CustomBinaryReader StreamReader { get; set; } - /// /// Used to write lines to server /// @@ -71,8 +66,6 @@ internal TcpConnection(ProxyServer proxyServer) /// public void Dispose() { - StreamReader?.Dispose(); - Stream?.Dispose(); TcpClient.CloseSocket(); diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs index 178af65a4..0839f4768 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs @@ -93,20 +93,17 @@ internal async Task CreateClient(string remoteHostName, int remot await writer.WriteRequestAsync(connectRequest, cancellationToken: cancellationToken); - using (var reader = new CustomBinaryReader(stream, proxyServer.BufferSize)) - { - string httpStatus = await reader.ReadLineAsync(cancellationToken); - - Response.ParseResponseLine(httpStatus, out _, out int statusCode, out string statusDescription); + string httpStatus = await stream.ReadLineAsync(cancellationToken); - if (statusCode != 200 && !statusDescription.EqualsIgnoreCase("OK") - && !statusDescription.EqualsIgnoreCase("Connection Established")) - { - throw new Exception("Upstream proxy failed to create a secure tunnel"); - } + Response.ParseResponseLine(httpStatus, out _, out int statusCode, out string statusDescription); - await reader.ReadAndIgnoreAllLinesAsync(cancellationToken); + if (statusCode != 200 && !statusDescription.EqualsIgnoreCase("OK") + && !statusDescription.EqualsIgnoreCase("Connection Established")) + { + throw new Exception("Upstream proxy failed to create a secure tunnel"); } + + await stream.ReadAndIgnoreAllLinesAsync(cancellationToken); } if (decryptSsl) @@ -152,7 +149,6 @@ internal async Task CreateClient(string remoteHostName, int remot IsHttp2Supported = http2Supported, UseUpstreamProxy = useUpstreamProxy, TcpClient = client, - StreamReader = new CustomBinaryReader(stream, proxyServer.BufferSize), StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferSize), Stream = stream, Version = httpVersion diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index 12e9643dd..27427301e 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -34,7 +34,6 @@ partial class ProxyServer /// The proxy endpoint. /// The client. /// The client stream. - /// The client stream reader. /// The client stream writer. /// The cancellation token source for this async task. /// @@ -45,8 +44,7 @@ partial class ProxyServer /// Is this a request from transparent endpoint? /// private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClient client, - CustomBufferedStream clientStream, CustomBinaryReader clientStreamReader, - HttpResponseWriter clientStreamWriter, + CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest, bool isTransparentEndPoint = false) { @@ -60,7 +58,7 @@ private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClient cl while (true) { // read the request line - string httpCmd = await clientStreamReader.ReadLineAsync(cancellationToken); + string httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (string.IsNullOrEmpty(httpCmd)) { @@ -81,7 +79,7 @@ private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClient cl out var version); //Read the request headers in to unique and non-unique header collections - await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.Headers, + await HeaderParser.ReadHeaders(clientStream, args.WebSession.Request.Headers, cancellationToken); Uri httpRemoteUri; @@ -124,7 +122,6 @@ await HeaderParser.ReadHeaders(clientStreamReader, args.WebSession.Request.Heade request.Method = httpMethod; request.HttpVersion = version; args.ProxyClient.ClientStream = clientStream; - args.ProxyClient.ClientStreamReader = clientStreamReader; args.ProxyClient.ClientStreamWriter = clientStreamWriter; //proxy authorization check @@ -198,7 +195,7 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, await connection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken); await connection.StreamWriter.WriteHeadersAsync(request.Headers, cancellationToken: cancellationToken); - string httpStatus = await connection.StreamReader.ReadLineAsync(cancellationToken); + string httpStatus = await connection.Stream.ReadLineAsync(cancellationToken); Response.ParseResponseLine(httpStatus, out var responseVersion, out int responseStatusCode, @@ -207,7 +204,7 @@ await connection.StreamWriter.WriteHeadersAsync(request.Headers, response.StatusCode = responseStatusCode; response.StatusDescription = responseStatusDescription; - await HeaderParser.ReadHeaders(connection.StreamReader, response.Headers, + await HeaderParser.ReadHeaders(connection.Stream, response.Headers, cancellationToken); if (!args.IsTransparent) diff --git a/Titanium.Web.Proxy/Titanium.Web.Proxy.Docs.csproj b/Titanium.Web.Proxy/Titanium.Web.Proxy.Docs.csproj index 7502e9dde..311ac990e 100644 --- a/Titanium.Web.Proxy/Titanium.Web.Proxy.Docs.csproj +++ b/Titanium.Web.Proxy/Titanium.Web.Proxy.Docs.csproj @@ -37,8 +37,8 @@ ..\packages\Portable.BouncyCastle.1.8.2\lib\net40\BouncyCastle.Crypto.dll - - ..\packages\StreamExtended.1.0.147-beta\lib\net45\StreamExtended.dll + + ..\packages\StreamExtended.1.0.160-beta\lib\net45\StreamExtended.dll diff --git a/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj b/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj index 6bdbd053e..051979fd6 100644 --- a/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj +++ b/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj @@ -13,7 +13,7 @@ - + diff --git a/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec b/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec index 715bb6199..7a6d4ced2 100644 --- a/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec +++ b/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec @@ -14,7 +14,7 @@ Copyright © Titanium. All rights reserved. - + diff --git a/Titanium.Web.Proxy/TransparentClientHandler.cs b/Titanium.Web.Proxy/TransparentClientHandler.cs index bc48be95a..5c06e5256 100644 --- a/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -30,7 +30,6 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcp var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); - var clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); try @@ -73,8 +72,6 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcp //HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); - clientStreamReader.Dispose(); - clientStreamReader = new CustomBinaryReader(clientStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); } catch (Exception e) @@ -126,12 +123,11 @@ await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, //HTTPS server created - we can now decrypt the client's traffic //Now create the request - await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamReader, - clientStreamWriter, cancellationTokenSource, isHttps ? httpsHostName : null, null, true); + await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamWriter, + cancellationTokenSource, isHttps ? httpsHostName : null, null, true); } finally { - clientStreamReader.Dispose(); clientStream.Dispose(); if (!cancellationTokenSource.IsCancellationRequested) { diff --git a/Titanium.Web.Proxy/packages.config b/Titanium.Web.Proxy/packages.config index a882527f8..2a2a3a11a 100644 --- a/Titanium.Web.Proxy/packages.config +++ b/Titanium.Web.Proxy/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file From 7baee70f6e50fd7e8d99c2ea6685624641d547f7 Mon Sep 17 00:00:00 2001 From: buildbot121 Date: Mon, 30 Apr 2018 08:27:46 -0700 Subject: [PATCH 02/23] API documentation update by build server --- ...y.EventArguments.SessionEventArgsBase.html | 4 +- .../Titanium.Web.Proxy.EventArguments.html | 3 -- docs/api/toc.html | 3 -- docs/index.json | 9 +--- docs/xrefmap.yml | 45 ------------------- 5 files changed, 4 insertions(+), 60 deletions(-) diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html index 689266428..32e7d608b 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html @@ -492,7 +492,7 @@
Event Type
- EventHandler<DataEventArgs> + EventHandler<StreamExtended.Network.DataEventArgs> @@ -517,7 +517,7 @@
Event Type
- EventHandler<DataEventArgs> + EventHandler<StreamExtended.Network.DataEventArgs> diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.html b/docs/api/Titanium.Web.Proxy.EventArguments.html index 906837d86..848a7870f 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.html @@ -96,9 +96,6 @@

CertificateValidationEventArgs

An argument passed on to the user for validating the server certificate during SSL authentication.

-
-

DataEventArgs

-

Wraps the data sent/received by a proxy server instance.

MultipartRequestPartSentEventArgs

Class that wraps the multipart sent request arguments.

diff --git a/docs/api/toc.html b/docs/api/toc.html index d0edb20cc..841c262c6 100644 --- a/docs/api/toc.html +++ b/docs/api/toc.html @@ -40,9 +40,6 @@
  • CertificateValidationEventArgs
  • -
  • - DataEventArgs -
  • MultipartRequestPartSentEventArgs
  • diff --git a/docs/index.json b/docs/index.json index 25e23571d..1383ac9b1 100644 --- a/docs/index.json +++ b/docs/index.json @@ -19,15 +19,10 @@ "title": "Class CertificateValidationEventArgs | Titanium Web Proxy", "keywords": "Class CertificateValidationEventArgs An argument passed on to the user for validating the server certificate during SSL authentication. Inheritance Object EventArgs CertificateValidationEventArgs Inherited Members EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class CertificateValidationEventArgs : EventArgs Properties Certificate Server certificate. Declaration public X509Certificate Certificate { get; } Property Value Type Description X509Certificate Chain Certificate chain. Declaration public X509Chain Chain { get; } Property Value Type Description X509Chain IsValid Is the given server certificate valid? Declaration public bool IsValid { get; set; } Property Value Type Description Boolean SslPolicyErrors SSL policy errors. Declaration public SslPolicyErrors SslPolicyErrors { get; } Property Value Type Description SslPolicyErrors" }, - "api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html": { - "href": "api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html", - "title": "Class DataEventArgs | Titanium Web Proxy", - "keywords": "Class DataEventArgs Wraps the data sent/received by a proxy server instance. Inheritance Object EventArgs DataEventArgs Inherited Members EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class DataEventArgs : EventArgs Properties Buffer The buffer with data. Declaration public byte[] Buffer { get; } Property Value Type Description System.Byte [] Count Length from offset in buffer with valid data. Declaration public int Count { get; } Property Value Type Description Int32 Offset Offset in buffer from which valid data begins. Declaration public int Offset { get; } Property Value Type Description Int32" - }, "api/Titanium.Web.Proxy.EventArguments.html": { "href": "api/Titanium.Web.Proxy.EventArguments.html", "title": "Namespace Titanium.Web.Proxy.EventArguments | Titanium Web Proxy", - "keywords": "Namespace Titanium.Web.Proxy.EventArguments Classes BeforeSslAuthenticateEventArgs This is used in transparent endpoint before authenticating client. CertificateSelectionEventArgs An argument passed on to user for client certificate selection during mutual SSL authentication. CertificateValidationEventArgs An argument passed on to the user for validating the server certificate during SSL authentication. DataEventArgs Wraps the data sent/received by a proxy server instance. MultipartRequestPartSentEventArgs Class that wraps the multipart sent request arguments. SessionEventArgs Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. TunnelConnectSessionEventArgs A class that wraps the state when a tunnel connect event happen for Explicit endpoints. Delegates AsyncEventHandler A generic asynchronous event handler used by the proxy." + "keywords": "Namespace Titanium.Web.Proxy.EventArguments Classes BeforeSslAuthenticateEventArgs This is used in transparent endpoint before authenticating client. CertificateSelectionEventArgs An argument passed on to user for client certificate selection during mutual SSL authentication. CertificateValidationEventArgs An argument passed on to the user for validating the server certificate during SSL authentication. MultipartRequestPartSentEventArgs Class that wraps the multipart sent request arguments. SessionEventArgs Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. TunnelConnectSessionEventArgs A class that wraps the state when a tunnel connect event happen for Explicit endpoints. Delegates AsyncEventHandler A generic asynchronous event handler used by the proxy." }, "api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html": { "href": "api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html", @@ -42,7 +37,7 @@ "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html": { "href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html", "title": "Class SessionEventArgsBase | Titanium Web Proxy", - "keywords": "Class SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs TunnelConnectSessionEventArgs Implements IDisposable Inherited Members EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public abstract class SessionEventArgsBase : EventArgs, IDisposable Constructors SessionEventArgsBase(Int32, ProxyEndPoint, CancellationTokenSource, Request, ExceptionHandler) Declaration protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request, ExceptionHandler exceptionFunc) Parameters Type Name Description Int32 bufferSize ProxyEndPoint endPoint CancellationTokenSource cancellationTokenSource Request request ExceptionHandler exceptionFunc Fields BufferSize Size of Buffers used by this object Declaration protected readonly int BufferSize Field Value Type Description Int32 ExceptionFunc Declaration protected readonly ExceptionHandler ExceptionFunc Field Value Type Description ExceptionHandler Properties ClientEndPoint Client End Point. Declaration public IPEndPoint ClientEndPoint { get; } Property Value Type Description IPEndPoint CustomUpStreamProxyUsed Are we using a custom upstream HTTP(S) proxy? Declaration public ExternalProxy CustomUpStreamProxyUsed { get; } Property Value Type Description ExternalProxy Exception The last exception that happened. Declaration public Exception Exception { get; } Property Value Type Description Exception Id Returns a unique Id for this request/response session which is same as the RequestId of WebSession. Declaration public Guid Id { get; } Property Value Type Description Guid IsHttps Does this session uses SSL? Declaration public bool IsHttps { get; } Property Value Type Description Boolean IsTransparent Is this a transparent endpoint? Declaration public bool IsTransparent { get; } Property Value Type Description Boolean LocalEndPoint Local endpoint via which we make the request. Declaration public ProxyEndPoint LocalEndPoint { get; } Property Value Type Description ProxyEndPoint WebSession A web session corresponding to a single request/response sequence within a proxy connection. Declaration public HttpWebClient WebSession { get; } Property Value Type Description HttpWebClient Methods Dispose() Implements cleanup here. Declaration public virtual void Dispose() TerminateSession() Terminates the session abruptly by terminating client/server connections. Declaration public void TerminateSession() Events DataReceived Fired when data is received within this session from client/server. Declaration public event EventHandler DataReceived Event Type Type Description EventHandler < DataEventArgs > DataSent Fired when data is sent within this session to server/client. Declaration public event EventHandler DataSent Event Type Type Description EventHandler < DataEventArgs > Implements System.IDisposable" + "keywords": "Class SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs TunnelConnectSessionEventArgs Implements IDisposable Inherited Members EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public abstract class SessionEventArgsBase : EventArgs, IDisposable Constructors SessionEventArgsBase(Int32, ProxyEndPoint, CancellationTokenSource, Request, ExceptionHandler) Declaration protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request, ExceptionHandler exceptionFunc) Parameters Type Name Description Int32 bufferSize ProxyEndPoint endPoint CancellationTokenSource cancellationTokenSource Request request ExceptionHandler exceptionFunc Fields BufferSize Size of Buffers used by this object Declaration protected readonly int BufferSize Field Value Type Description Int32 ExceptionFunc Declaration protected readonly ExceptionHandler ExceptionFunc Field Value Type Description ExceptionHandler Properties ClientEndPoint Client End Point. Declaration public IPEndPoint ClientEndPoint { get; } Property Value Type Description IPEndPoint CustomUpStreamProxyUsed Are we using a custom upstream HTTP(S) proxy? Declaration public ExternalProxy CustomUpStreamProxyUsed { get; } Property Value Type Description ExternalProxy Exception The last exception that happened. Declaration public Exception Exception { get; } Property Value Type Description Exception Id Returns a unique Id for this request/response session which is same as the RequestId of WebSession. Declaration public Guid Id { get; } Property Value Type Description Guid IsHttps Does this session uses SSL? Declaration public bool IsHttps { get; } Property Value Type Description Boolean IsTransparent Is this a transparent endpoint? Declaration public bool IsTransparent { get; } Property Value Type Description Boolean LocalEndPoint Local endpoint via which we make the request. Declaration public ProxyEndPoint LocalEndPoint { get; } Property Value Type Description ProxyEndPoint WebSession A web session corresponding to a single request/response sequence within a proxy connection. Declaration public HttpWebClient WebSession { get; } Property Value Type Description HttpWebClient Methods Dispose() Implements cleanup here. Declaration public virtual void Dispose() TerminateSession() Terminates the session abruptly by terminating client/server connections. Declaration public void TerminateSession() Events DataReceived Fired when data is received within this session from client/server. Declaration public event EventHandler DataReceived Event Type Type Description EventHandler < StreamExtended.Network.DataEventArgs > DataSent Fired when data is sent within this session to server/client. Declaration public event EventHandler DataSent Event Type Type Description EventHandler < StreamExtended.Network.DataEventArgs > Implements System.IDisposable" }, "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html": { "href": "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html", diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index 68c7f9424..b3bb7bc4b 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -209,51 +209,6 @@ references: isSpec: "True" fullName: Titanium.Web.Proxy.EventArguments.CertificateValidationEventArgs.SslPolicyErrors nameWithType: CertificateValidationEventArgs.SslPolicyErrors -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs - name: DataEventArgs - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html - commentId: T:Titanium.Web.Proxy.EventArguments.DataEventArgs - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs - nameWithType: DataEventArgs -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer - name: Buffer - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html#Titanium_Web_Proxy_EventArguments_DataEventArgs_Buffer - commentId: P:Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer - nameWithType: DataEventArgs.Buffer -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer* - name: Buffer - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html#Titanium_Web_Proxy_EventArguments_DataEventArgs_Buffer_ - commentId: Overload:Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer - isSpec: "True" - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs.Buffer - nameWithType: DataEventArgs.Buffer -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs.Count - name: Count - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html#Titanium_Web_Proxy_EventArguments_DataEventArgs_Count - commentId: P:Titanium.Web.Proxy.EventArguments.DataEventArgs.Count - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs.Count - nameWithType: DataEventArgs.Count -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs.Count* - name: Count - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html#Titanium_Web_Proxy_EventArguments_DataEventArgs_Count_ - commentId: Overload:Titanium.Web.Proxy.EventArguments.DataEventArgs.Count - isSpec: "True" - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs.Count - nameWithType: DataEventArgs.Count -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset - name: Offset - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html#Titanium_Web_Proxy_EventArguments_DataEventArgs_Offset - commentId: P:Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset - nameWithType: DataEventArgs.Offset -- uid: Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset* - name: Offset - href: api/Titanium.Web.Proxy.EventArguments.DataEventArgs.html#Titanium_Web_Proxy_EventArguments_DataEventArgs_Offset_ - commentId: Overload:Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset - isSpec: "True" - fullName: Titanium.Web.Proxy.EventArguments.DataEventArgs.Offset - nameWithType: DataEventArgs.Offset - uid: Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs name: MultipartRequestPartSentEventArgs href: api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html From db2b48a6e8fe683f30b7a0da2038e3305ea29d1f Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 30 Apr 2018 17:54:21 +0200 Subject: [PATCH 03/23] simplify compressionfactory, usre stream reader interface when only the read methods are used, stream dispose in getbody --- .../Compression/CompressionFactory.cs | 12 +++++------- .../DecompressionFactory.cs | 15 ++++++--------- .../Compression/DeflateCompression.cs | 16 ---------------- .../Compression/GZipCompression.cs | 16 ---------------- Titanium.Web.Proxy/Compression/ICompression.cs | 12 ------------ .../Decompression/DeflateDecompression.cs | 16 ---------------- .../Decompression/GZipDecompression.cs | 16 ---------------- .../Decompression/IDecompression.cs | 12 ------------ .../EventArguments/SessionEventArgs.cs | 10 ++++++---- Titanium.Web.Proxy/Helpers/HttpHelper.cs | 18 +++++++++--------- Titanium.Web.Proxy/Http/RequestResponseBase.cs | 3 +-- 11 files changed, 27 insertions(+), 119 deletions(-) rename Titanium.Web.Proxy/{Decompression => Compression}/DecompressionFactory.cs (59%) delete mode 100644 Titanium.Web.Proxy/Compression/DeflateCompression.cs delete mode 100644 Titanium.Web.Proxy/Compression/GZipCompression.cs delete mode 100644 Titanium.Web.Proxy/Compression/ICompression.cs delete mode 100644 Titanium.Web.Proxy/Decompression/DeflateDecompression.cs delete mode 100644 Titanium.Web.Proxy/Decompression/GZipDecompression.cs delete mode 100644 Titanium.Web.Proxy/Decompression/IDecompression.cs diff --git a/Titanium.Web.Proxy/Compression/CompressionFactory.cs b/Titanium.Web.Proxy/Compression/CompressionFactory.cs index a21f24fbf..fdae2ce3d 100644 --- a/Titanium.Web.Proxy/Compression/CompressionFactory.cs +++ b/Titanium.Web.Proxy/Compression/CompressionFactory.cs @@ -1,4 +1,6 @@ using System; +using System.IO; +using System.IO.Compression; using Titanium.Web.Proxy.Http; namespace Titanium.Web.Proxy.Compression @@ -8,18 +10,14 @@ namespace Titanium.Web.Proxy.Compression /// internal static class CompressionFactory { - //cache - private static readonly ICompression gzip = new GZipCompression(); - private static readonly ICompression deflate = new DeflateCompression(); - - internal static ICompression GetCompression(string type) + internal static Stream Create(string type, Stream stream, bool leaveOpen = true) { switch (type) { case KnownHeaders.ContentEncodingGzip: - return gzip; + return new GZipStream(stream, CompressionMode.Compress, leaveOpen); case KnownHeaders.ContentEncodingDeflate: - return deflate; + return new DeflateStream(stream, CompressionMode.Compress, leaveOpen); default: throw new Exception($"Unsupported compression mode: {type}"); } diff --git a/Titanium.Web.Proxy/Decompression/DecompressionFactory.cs b/Titanium.Web.Proxy/Compression/DecompressionFactory.cs similarity index 59% rename from Titanium.Web.Proxy/Decompression/DecompressionFactory.cs rename to Titanium.Web.Proxy/Compression/DecompressionFactory.cs index 66ba2eb24..f8a0fc1dd 100644 --- a/Titanium.Web.Proxy/Decompression/DecompressionFactory.cs +++ b/Titanium.Web.Proxy/Compression/DecompressionFactory.cs @@ -1,26 +1,23 @@ using System; +using System.IO; +using System.IO.Compression; using Titanium.Web.Proxy.Http; -namespace Titanium.Web.Proxy.Decompression +namespace Titanium.Web.Proxy.Compression { /// /// A factory to generate the de-compression methods based on the type of compression /// internal class DecompressionFactory { - //cache - private static readonly IDecompression gzip = new GZipDecompression(); - - private static readonly IDecompression deflate = new DeflateDecompression(); - - internal static IDecompression Create(string type) + internal static Stream Create(string type, Stream stream, bool leaveOpen = true) { switch (type) { case KnownHeaders.ContentEncodingGzip: - return gzip; + return new GZipStream(stream, CompressionMode.Decompress, leaveOpen); case KnownHeaders.ContentEncodingDeflate: - return deflate; + return new DeflateStream(stream, CompressionMode.Decompress, leaveOpen); default: throw new Exception($"Unsupported decompression mode: {type}"); } diff --git a/Titanium.Web.Proxy/Compression/DeflateCompression.cs b/Titanium.Web.Proxy/Compression/DeflateCompression.cs deleted file mode 100644 index c6c0a7414..000000000 --- a/Titanium.Web.Proxy/Compression/DeflateCompression.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; -using System.IO.Compression; - -namespace Titanium.Web.Proxy.Compression -{ - /// - /// Concrete implementation of deflate compression - /// - internal class DeflateCompression : ICompression - { - public Stream GetStream(Stream stream) - { - return new DeflateStream(stream, CompressionMode.Compress, true); - } - } -} diff --git a/Titanium.Web.Proxy/Compression/GZipCompression.cs b/Titanium.Web.Proxy/Compression/GZipCompression.cs deleted file mode 100644 index 448912b87..000000000 --- a/Titanium.Web.Proxy/Compression/GZipCompression.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; -using System.IO.Compression; - -namespace Titanium.Web.Proxy.Compression -{ - /// - /// concreate implementation of gzip compression - /// - internal class GZipCompression : ICompression - { - public Stream GetStream(Stream stream) - { - return new GZipStream(stream, CompressionMode.Compress, true); - } - } -} diff --git a/Titanium.Web.Proxy/Compression/ICompression.cs b/Titanium.Web.Proxy/Compression/ICompression.cs deleted file mode 100644 index 3958ec030..000000000 --- a/Titanium.Web.Proxy/Compression/ICompression.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.IO; - -namespace Titanium.Web.Proxy.Compression -{ - /// - /// An inteface for http compression - /// - internal interface ICompression - { - Stream GetStream(Stream stream); - } -} diff --git a/Titanium.Web.Proxy/Decompression/DeflateDecompression.cs b/Titanium.Web.Proxy/Decompression/DeflateDecompression.cs deleted file mode 100644 index 0f9fd3488..000000000 --- a/Titanium.Web.Proxy/Decompression/DeflateDecompression.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; -using System.IO.Compression; - -namespace Titanium.Web.Proxy.Decompression -{ - /// - /// concrete implementation of deflate de-compression - /// - internal class DeflateDecompression : IDecompression - { - public Stream GetStream(Stream stream) - { - return new DeflateStream(stream, CompressionMode.Decompress, true); - } - } -} diff --git a/Titanium.Web.Proxy/Decompression/GZipDecompression.cs b/Titanium.Web.Proxy/Decompression/GZipDecompression.cs deleted file mode 100644 index ea24ec2c7..000000000 --- a/Titanium.Web.Proxy/Decompression/GZipDecompression.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; -using System.IO.Compression; - -namespace Titanium.Web.Proxy.Decompression -{ - /// - /// concrete implementation of gzip de-compression - /// - internal class GZipDecompression : IDecompression - { - public Stream GetStream(Stream stream) - { - return new GZipStream(stream, CompressionMode.Decompress, true); - } - } -} diff --git a/Titanium.Web.Proxy/Decompression/IDecompression.cs b/Titanium.Web.Proxy/Decompression/IDecompression.cs deleted file mode 100644 index d0b6b9dc3..000000000 --- a/Titanium.Web.Proxy/Decompression/IDecompression.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.IO; - -namespace Titanium.Web.Proxy.Decompression -{ - /// - /// An interface for decompression - /// - internal interface IDecompression - { - Stream GetStream(Stream stream); - } -} diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs index d4508d9da..2dde209c2 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using StreamExtended.Helpers; using StreamExtended.Network; -using Titanium.Web.Proxy.Decompression; +using Titanium.Web.Proxy.Compression; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http.Responses; @@ -256,13 +256,15 @@ private async Task CopyBodyAsync(bool isRequest, HttpWriter writer, Transformati if (transformation == TransformationMode.Uncompress && contentEncoding != null) { - s = decompressStream = DecompressionFactory.Create(contentEncoding).GetStream(s); + s = decompressStream = DecompressionFactory.Create(contentEncoding, s); } try { - var bufStream = new CustomBufferedStream(s, BufferSize, true); - await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken); + using (var bufStream = new CustomBufferedStream(s, BufferSize, true)) + { + await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken); + } } finally { diff --git a/Titanium.Web.Proxy/Helpers/HttpHelper.cs b/Titanium.Web.Proxy/Helpers/HttpHelper.cs index ef314f2f7..7b3269ce9 100644 --- a/Titanium.Web.Proxy/Helpers/HttpHelper.cs +++ b/Titanium.Web.Proxy/Helpers/HttpHelper.cs @@ -118,38 +118,38 @@ internal static string GetWildCardDomainName(string hostname) /// /// Determines whether is connect method. /// - /// The client stream. + /// The client stream reader. /// 1: when CONNECT, 0: when valid HTTP method, -1: otherwise - internal static Task IsConnectMethod(CustomBufferedStream clientStream) + internal static Task IsConnectMethod(ICustomStreamReader clientStreamReader) { - return StartsWith(clientStream, "CONNECT"); + return StartsWith(clientStreamReader, "CONNECT"); } /// /// Determines whether is pri method (HTTP/2). /// - /// The client stream. + /// The client stream reader. /// 1: when PRI, 0: when valid HTTP method, -1: otherwise - internal static Task IsPriMethod(CustomBufferedStream clientStream) + internal static Task IsPriMethod(ICustomStreamReader clientStreamReader) { - return StartsWith(clientStream, "PRI"); + return StartsWith(clientStreamReader, "PRI"); } /// /// Determines whether the stream starts with the given string. /// - /// The client stream. + /// The client stream reader. /// The expected start. /// /// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise /// - private static async Task StartsWith(CustomBufferedStream clientStream, string expectedStart) + private static async Task StartsWith(ICustomStreamReader clientStreamReader, string expectedStart) { bool isExpected = true; int legthToCheck = 10; for (int i = 0; i < legthToCheck; i++) { - int b = await clientStream.PeekByteAsync(i); + int b = await clientStreamReader.PeekByteAsync(i); if (b == -1) { return -1; diff --git a/Titanium.Web.Proxy/Http/RequestResponseBase.cs b/Titanium.Web.Proxy/Http/RequestResponseBase.cs index aa32fcd1a..d00c7de0a 100644 --- a/Titanium.Web.Proxy/Http/RequestResponseBase.cs +++ b/Titanium.Web.Proxy/Http/RequestResponseBase.cs @@ -177,10 +177,9 @@ internal set /// internal byte[] GetCompressedBody(string encodingType, byte[] body) { - var compressor = CompressionFactory.GetCompression(encodingType); using (var ms = new MemoryStream()) { - using (var zip = compressor.GetStream(ms)) + using (var zip = CompressionFactory.Create(encodingType, ms)) { zip.Write(body, 0, body.Length); } From 927d2b15e407352a09a887dcdabb3104bdd3822e Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 30 Apr 2018 22:25:27 +0200 Subject: [PATCH 04/23] TcpClientConnection class --- .../MainWindow.xaml.cs | 1 - .../EventArguments/SessionEventArgs.cs | 1 + .../EventArguments/SessionEventArgsBase.cs | 2 +- Titanium.Web.Proxy/ExplicitClientHandler.cs | 16 ++++--- Titanium.Web.Proxy/Helpers/Tcp.cs | 5 +- Titanium.Web.Proxy/Http/HttpWebClient.cs | 10 ++-- .../Network/DebugCustomBufferedStream.cs | 34 ++++++++++++-- Titanium.Web.Proxy/Network/ProxyClient.cs | 8 ++-- .../Network/Tcp/TcpClientConnection.cs | 46 ++++++++++++++++++ .../Network/Tcp/TcpConnectionFactory.cs | 21 ++++----- ...cpConnection.cs => TcpServerConnection.cs} | 9 ++-- Titanium.Web.Proxy/ProxyServer.cs | 14 ++---- Titanium.Web.Proxy/RequestHandler.cs | 47 +++++++++---------- .../TransparentClientHandler.cs | 9 ++-- Titanium.Web.Proxy/WinAuthHandler.cs | 2 +- 15 files changed, 145 insertions(+), 80 deletions(-) create mode 100644 Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs rename Titanium.Web.Proxy/Network/Tcp/{TcpConnection.cs => TcpServerConnection.cs} (87%) diff --git a/Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs b/Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs index 272858d00..803ee3169 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs +++ b/Examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs @@ -9,7 +9,6 @@ using System.Windows.Controls; using System.Windows.Input; using Titanium.Web.Proxy.EventArguments; -using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Models; diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs index 2dde209c2..7970e21a7 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs @@ -11,6 +11,7 @@ using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http.Responses; using Titanium.Web.Proxy.Models; +using Titanium.Web.Proxy.Network; namespace Titanium.Web.Proxy.EventArguments { diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index 98ac1e355..f8741bb3b 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -87,7 +87,7 @@ protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, /// /// Client End Point. /// - public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint; + public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.ClientConnection.RemoteEndPoint; /// /// A web session corresponding to a single request/response sequence diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index ff5d828ec..f78ada968 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -15,6 +15,8 @@ using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Models; +using Titanium.Web.Proxy.Network; +using Titanium.Web.Proxy.Network.Tcp; namespace Titanium.Web.Proxy { @@ -25,14 +27,14 @@ partial class ProxyServer /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy /// /// The explicit endpoint. - /// The client. + /// The client connection. /// The task. - private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient) + private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClientConnection clientConnection) { var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; - var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); + var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); @@ -67,7 +69,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest, cancellationTokenSource, ExceptionFunc); - connectArgs.ProxyClient.TcpClient = tcpClient; + connectArgs.ProxyClient.ClientConnection = clientConnection; connectArgs.ProxyClient.ClientStream = clientStream; await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc); @@ -158,7 +160,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, options.ApplicationProtocols = clientHelloInfo.GetAlpn(); if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0) { - options.ApplicationProtocols = Titanium.Web.Proxy.Extensions.SslExtensions.Http11ProtocolAsList; + options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList; } } @@ -270,13 +272,13 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, - connectArgs.CancellationTokenSource, ExceptionFunc); + connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); } } } //Now create the request - await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, + await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); } diff --git a/Titanium.Web.Proxy/Helpers/Tcp.cs b/Titanium.Web.Proxy/Helpers/Tcp.cs index 1b079d921..ebb57c6c5 100644 --- a/Titanium.Web.Proxy/Helpers/Tcp.cs +++ b/Titanium.Web.Proxy/Helpers/Tcp.cs @@ -265,15 +265,14 @@ internal static Task SendRaw(Stream clientStream, Stream serverStream, int buffe /// /// /// + /// /// /// internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize, Action onDataSend, Action onDataReceive, - CancellationTokenSource cancellationTokenSource, + CancellationTokenSource cancellationTokenSource, Guid connectionId, ExceptionHandler exceptionFunc) { - var connectionId = Guid.NewGuid(); - //Now async relay all server=>client & client=>server data var sendRelay = CopyHttp2FrameAsync(clientStream, serverStream, onDataSend, bufferSize, connectionId, diff --git a/Titanium.Web.Proxy/Http/HttpWebClient.cs b/Titanium.Web.Proxy/Http/HttpWebClient.cs index bb92dee81..c3edf87a3 100644 --- a/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -28,7 +28,7 @@ internal HttpWebClient(int bufferSize, Request request = null, Response response /// /// Connection to server /// - internal TcpConnection ServerConnection { get; set; } + internal TcpServerConnection ServerConnection { get; set; } /// /// Request ID. @@ -69,11 +69,11 @@ internal HttpWebClient(int bufferSize, Request request = null, Response response /// /// Set the tcp connection to server used by this webclient /// - /// Instance of - internal void SetConnection(TcpConnection connection) + /// Instance of + internal void SetConnection(TcpServerConnection serverConnection) { - connection.LastAccess = DateTime.Now; - ServerConnection = connection; + serverConnection.LastAccess = DateTime.Now; + ServerConnection = serverConnection; } /// diff --git a/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs b/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs index 92698ac04..69e29baef 100644 --- a/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs +++ b/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs @@ -1,5 +1,7 @@ #if DEBUG +using System; using System.IO; +using System.Text; using System.Threading; using StreamExtended.Network; @@ -15,11 +17,11 @@ internal class DebugCustomBufferedStream : CustomBufferedStream private readonly FileStream fileStreamSent; - public DebugCustomBufferedStream(Stream baseStream, int bufferSize) : base(baseStream, bufferSize) + public DebugCustomBufferedStream(Guid connectionId, string type, Stream baseStream, int bufferSize, bool leaveOpen = false) : base(baseStream, bufferSize, leaveOpen) { Counter = Interlocked.Increment(ref counter); - fileStreamSent = new FileStream(Path.Combine(basePath, $"{Counter}_sent.dat"), FileMode.Create); - fileStreamReceived = new FileStream(Path.Combine(basePath, $"{Counter}_received.dat"), FileMode.Create); + fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create); + fileStreamReceived = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_received.dat"), FileMode.Create); } public int Counter { get; } @@ -27,18 +29,42 @@ public DebugCustomBufferedStream(Stream baseStream, int bufferSize) : base(baseS protected override void OnDataWrite(byte[] buffer, int offset, int count) { fileStreamSent.Write(buffer, offset, count); + Flush(); } protected override void OnDataRead(byte[] buffer, int offset, int count) { fileStreamReceived.Write(buffer, offset, count); + Flush(); } + public void LogException(Exception ex) + { + var data = Encoding.UTF8.GetBytes("EXCEPTION: " + ex); + fileStreamReceived.Write(data, 0, data.Length); + fileStreamReceived.Flush(); + } public override void Flush() { fileStreamSent.Flush(true); fileStreamReceived.Flush(true); - base.Flush(); + + if (CanWrite) + { + base.Flush(); + } + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Flush(); + fileStreamSent.Dispose(); + fileStreamReceived.Dispose(); + } + + base.Dispose(disposing); } } } diff --git a/Titanium.Web.Proxy/Network/ProxyClient.cs b/Titanium.Web.Proxy/Network/ProxyClient.cs index 7e1e387ea..3611bdd8f 100644 --- a/Titanium.Web.Proxy/Network/ProxyClient.cs +++ b/Titanium.Web.Proxy/Network/ProxyClient.cs @@ -1,6 +1,6 @@ -using System.Net.Sockets; -using StreamExtended.Network; +using StreamExtended.Network; using Titanium.Web.Proxy.Helpers; +using Titanium.Web.Proxy.Network.Tcp; namespace Titanium.Web.Proxy.Network { @@ -10,9 +10,9 @@ namespace Titanium.Web.Proxy.Network internal class ProxyClient { /// - /// TcpClient used to communicate with client + /// TcpClient connection used to communicate with client /// - internal TcpClient TcpClient { get; set; } + internal TcpClientConnection ClientConnection { get; set; } /// /// Holds the stream to client diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs b/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs new file mode 100644 index 000000000..11fe07000 --- /dev/null +++ b/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using Titanium.Web.Proxy.Extensions; + +namespace Titanium.Web.Proxy.Network.Tcp +{ + /// + /// An object that holds TcpConnection to a particular server and port + /// + internal class TcpClientConnection : IDisposable + { + internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient) + { + this.tcpClient = tcpClient; + this.proxyServer = proxyServer; + this.proxyServer.UpdateClientConnectionCount(true); + } + + private ProxyServer proxyServer { get; } + + public Guid Id { get; } = Guid.NewGuid(); + + public EndPoint LocalEndPoint => tcpClient.Client.LocalEndPoint; + + public EndPoint RemoteEndPoint => tcpClient.Client.RemoteEndPoint; + + private readonly TcpClient tcpClient; + + public Stream GetStream() + { + return tcpClient.GetStream(); + } + + /// + /// Dispose. + /// + public void Dispose() + { + tcpClient.CloseSocket(); + + proxyServer.UpdateClientConnectionCount(false); + } + } +} diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs index 0839f4768..82d09663d 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs @@ -32,7 +32,7 @@ internal class TcpConnectionFactory /// /// /// - internal async Task CreateClient(string remoteHostName, int remotePort, + internal async Task CreateClient(string remoteHostName, int remotePort, List applicationProtocols, Version httpVersion, bool decryptSsl, bool isConnect, ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy, CancellationToken cancellationToken) @@ -52,26 +52,26 @@ internal async Task CreateClient(string remoteHostName, int remot } } - TcpClient client = null; + TcpClient tcpClient = null; CustomBufferedStream stream = null; bool http2Supported = false; try { - client = new TcpClient(upStreamEndPoint); + tcpClient = new TcpClient(upStreamEndPoint); //If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections if (useUpstreamProxy) { - await client.ConnectAsync(externalProxy.HostName, externalProxy.Port); + await tcpClient.ConnectAsync(externalProxy.HostName, externalProxy.Port); } else { - await client.ConnectAsync(remoteHostName, remotePort); + await tcpClient.ConnectAsync(remoteHostName, remotePort); } - stream = new CustomBufferedStream(client.GetStream(), proxyServer.BufferSize); + stream = new CustomBufferedStream(tcpClient.GetStream(), proxyServer.BufferSize); if (useUpstreamProxy && (isConnect || decryptSsl)) { @@ -129,17 +129,17 @@ internal async Task CreateClient(string remoteHostName, int remot #endif } - client.ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; - client.SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; + tcpClient.ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; + tcpClient.SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; } catch (Exception) { stream?.Dispose(); - client?.Close(); + tcpClient?.Close(); throw; } - return new TcpConnection(proxyServer) + return new TcpServerConnection(proxyServer, tcpClient) { UpStreamProxy = externalProxy, UpStreamEndPoint = upStreamEndPoint, @@ -148,7 +148,6 @@ internal async Task CreateClient(string remoteHostName, int remot IsHttps = decryptSsl, IsHttp2Supported = http2Supported, UseUpstreamProxy = useUpstreamProxy, - TcpClient = client, StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferSize), Stream = stream, Version = httpVersion diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs b/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs similarity index 87% rename from Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs rename to Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs index 5a5048346..1c18b28be 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs @@ -11,10 +11,11 @@ namespace Titanium.Web.Proxy.Network.Tcp /// /// An object that holds TcpConnection to a particular server and port /// - internal class TcpConnection : IDisposable + internal class TcpServerConnection : IDisposable { - internal TcpConnection(ProxyServer proxyServer) + internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient) { + this.tcpClient = tcpClient; LastAccess = DateTime.Now; this.proxyServer = proxyServer; this.proxyServer.UpdateServerConnectionCount(true); @@ -44,7 +45,7 @@ internal TcpConnection(ProxyServer proxyServer) /// internal Version Version { get; set; } - internal TcpClient TcpClient { private get; set; } + private readonly TcpClient tcpClient; /// /// Used to write lines to server @@ -68,7 +69,7 @@ public void Dispose() { Stream?.Dispose(); - TcpClient.CloseSocket(); + tcpClient.CloseSocket(); proxyServer.UpdateServerConnectionCount(false); } diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index c01541703..341affb2d 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -8,7 +8,6 @@ using System.Threading; using System.Threading.Tasks; using Titanium.Web.Proxy.EventArguments; -using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers.WinHttp; using Titanium.Web.Proxy.Models; @@ -648,27 +647,20 @@ private void OnAcceptConnection(IAsyncResult asyn) private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint) { - UpdateClientConnectionCount(true); - tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000; - try + using (var clientConnection = new TcpClientConnection(this, tcpClient)) { if (endPoint is TransparentProxyEndPoint tep) { - await HandleClient(tep, tcpClient); + await HandleClient(tep, clientConnection); } else { - await HandleClient((ExplicitProxyEndPoint)endPoint, tcpClient); + await HandleClient((ExplicitProxyEndPoint)endPoint, clientConnection); } } - finally - { - UpdateClientConnectionCount(false); - tcpClient.CloseSocket(); - } } /// diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index 27427301e..eaf7e6102 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -1,6 +1,5 @@ using System; using System.Net; -using System.Net.Sockets; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -32,7 +31,7 @@ partial class ProxyServer /// client/server abruptly terminates connection or by normal HTTP termination. /// /// The proxy endpoint. - /// The client. + /// The client connection. /// The client stream. /// The client stream writer. /// The cancellation token source for this async task. @@ -43,13 +42,13 @@ partial class ProxyServer /// The Connect request if this is a HTTPS request from explicit endpoint. /// Is this a request from transparent endpoint? /// - private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClient client, + private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest, bool isTransparentEndPoint = false) { var cancellationToken = cancellationTokenSource.Token; - TcpConnection connection = null; + TcpServerConnection serverConnection = null; try { @@ -67,7 +66,7 @@ private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClient cl var args = new SessionEventArgs(BufferSize, endPoint, cancellationTokenSource, ExceptionFunc) { - ProxyClient = { TcpClient = client }, + ProxyClient = { ClientConnection = clientConnection }, WebSession = { ConnectRequest = connectRequest } }; @@ -173,29 +172,29 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, } //create a new connection if hostname/upstream end point changes - if (connection != null - && (!connection.HostName.Equals(request.RequestUri.Host, + if (serverConnection != null + && (!serverConnection.HostName.Equals(request.RequestUri.Host, StringComparison.OrdinalIgnoreCase) || args.WebSession.UpStreamEndPoint != null - && !args.WebSession.UpStreamEndPoint.Equals(connection.UpStreamEndPoint))) + && !args.WebSession.UpStreamEndPoint.Equals(serverConnection.UpStreamEndPoint))) { - connection.Dispose(); - connection = null; + serverConnection.Dispose(); + serverConnection = null; } - if (connection == null) + if (serverConnection == null) { - connection = await GetServerConnection(args, false, cancellationToken); + serverConnection = await GetServerConnection(args, false, cancellationToken); } //if upgrading to websocket then relay the requet without reading the contents if (request.UpgradeToWebSocket) { //prepare the prefix content - await connection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken); - await connection.StreamWriter.WriteHeadersAsync(request.Headers, + await serverConnection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken); + await serverConnection.StreamWriter.WriteHeadersAsync(request.Headers, cancellationToken: cancellationToken); - string httpStatus = await connection.Stream.ReadLineAsync(cancellationToken); + string httpStatus = await serverConnection.Stream.ReadLineAsync(cancellationToken); Response.ParseResponseLine(httpStatus, out var responseVersion, out int responseStatusCode, @@ -204,7 +203,7 @@ await connection.StreamWriter.WriteHeadersAsync(request.Headers, response.StatusCode = responseStatusCode; response.StatusDescription = responseStatusDescription; - await HeaderParser.ReadHeaders(connection.Stream, response.Headers, + await HeaderParser.ReadHeaders(serverConnection.Stream, response.Headers, cancellationToken); if (!args.IsTransparent) @@ -219,7 +218,7 @@ await clientStreamWriter.WriteResponseAsync(response, await InvokeBeforeResponse(args); } - await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, + await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferSize, (buffer, offset, count) => { args.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); }, cancellationTokenSource, ExceptionFunc); @@ -228,7 +227,7 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, } //construct the web request that we are going to issue on behalf of the client. - await HandleHttpSessionRequestInternal(connection, args); + await HandleHttpSessionRequestInternal(serverConnection, args); if (args.WebSession.ServerConnection == null) { @@ -265,17 +264,17 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, } finally { - connection?.Dispose(); + serverConnection?.Dispose(); } } /// /// Handle a specific session (request/response sequence) /// - /// The tcp connection. + /// The tcp connection. /// The session event arguments. /// - private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args) + private async Task HandleHttpSessionRequestInternal(TcpServerConnection serverConnection, SessionEventArgs args) { try { @@ -289,7 +288,7 @@ private async Task HandleHttpSessionRequestInternal(TcpConnection connection, Se //and see if server would return 100 conitinue if (request.ExpectContinue) { - args.WebSession.SetConnection(connection); + args.WebSession.SetConnection(serverConnection); await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent, cancellationToken); } @@ -316,7 +315,7 @@ await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpV //If expect continue is not enabled then set the connectio and send request headers if (!request.ExpectContinue) { - args.WebSession.SetConnection(connection); + args.WebSession.SetConnection(serverConnection); await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent, cancellationToken); } @@ -361,7 +360,7 @@ await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent /// Is this a CONNECT request. /// The cancellation token for this async task. /// - private async Task GetServerConnection(SessionEventArgsBase args, bool isConnect, + private async Task GetServerConnection(SessionEventArgsBase args, bool isConnect, CancellationToken cancellationToken) { ExternalProxy customUpStreamProxy = null; diff --git a/Titanium.Web.Proxy/TransparentClientHandler.cs b/Titanium.Web.Proxy/TransparentClientHandler.cs index 5c06e5256..283eba829 100644 --- a/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -11,6 +11,7 @@ using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Models; +using Titanium.Web.Proxy.Network.Tcp; namespace Titanium.Web.Proxy { @@ -21,14 +22,14 @@ partial class ProxyServer /// So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client /// /// The transparent endpoint. - /// The client. + /// The client connection. /// - private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient) + private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection) { var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; - var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); + var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); @@ -123,7 +124,7 @@ await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, //HTTPS server created - we can now decrypt the client's traffic //Now create the request - await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamWriter, + await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, isHttps ? httpsHostName : null, null, true); } finally diff --git a/Titanium.Web.Proxy/WinAuthHandler.cs b/Titanium.Web.Proxy/WinAuthHandler.cs index ad25c26af..7155c628c 100644 --- a/Titanium.Web.Proxy/WinAuthHandler.cs +++ b/Titanium.Web.Proxy/WinAuthHandler.cs @@ -172,7 +172,7 @@ internal async Task RewriteUnauthorizedResponse(SessionEventArgs args) // Add custom div to body to clarify that the proxy (not the client browser) failed authentication string authErrorMessage = "

    NTLM authentication through Titanium.Web.Proxy (" + - args.ProxyClient.TcpClient.Client.LocalEndPoint + + args.ProxyClient.ClientConnection.LocalEndPoint + ") failed. Please check credentials.

    "; string originalErrorMessage = "

    Response from remote web server below.


    "; From 59e3062d3e413a11dc07b83bd5948df5eca9b8b4 Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 30 Apr 2018 23:57:53 +0200 Subject: [PATCH 05/23] Increase timeout to 60 sec, because long polling usually uses 30 sec timeouts (https://tools.ietf.org/id/draft-loreto-http-bidirectional-07.html) therefor 30 sec receive timeout is not enough --- Titanium.Web.Proxy/ProxyServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index 341affb2d..f02596ab8 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -92,7 +92,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool trustRootCertificateAsAdmin = false) { //default values - ConnectionTimeOutSeconds = 30; + ConnectionTimeOutSeconds = 60; ProxyEndPoints = new List(); tcpConnectionFactory = new TcpConnectionFactory(); From bb6be9d40bc97a2eb5ce36cab993e41a246fbadc Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 1 May 2018 09:12:55 +0200 Subject: [PATCH 06/23] small exception handling improvement --- .../Exceptions/ProxyConnectException.cs | 31 +++++++++++++++++++ Titanium.Web.Proxy/ExplicitClientHandler.cs | 15 +++++---- .../Network/CertificateManager.cs | 10 ++---- Titanium.Web.Proxy/ProxyServer.cs | 13 ++++++++ .../TransparentClientHandler.cs | 23 ++++++++++++-- 5 files changed, 73 insertions(+), 19 deletions(-) create mode 100644 Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs diff --git a/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs b/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs new file mode 100644 index 000000000..bc6718df2 --- /dev/null +++ b/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs @@ -0,0 +1,31 @@ +using System; +using Titanium.Web.Proxy.EventArguments; + +namespace Titanium.Web.Proxy.Exceptions +{ + /// + /// Proxy Connection exception. + /// + public class ProxyConnectException : ProxyException + { + /// + /// Instantiate new instance + /// + /// Message for this exception + /// Associated inner exception + /// Instance of associated to the exception + internal ProxyConnectException(string message, Exception innerException, TunnelConnectSessionEventArgs connectEventArgs) : base( + message, innerException) + { + ConnectEventArgs = connectEventArgs; + } + + /// + /// Gets session info associated to the exception. + /// + /// + /// This object properties should not be edited. + /// + public TunnelConnectSessionEventArgs ConnectEventArgs { get; } + } +} diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index f78ada968..a24303c4f 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -177,10 +177,9 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, } catch (Exception e) { - ExceptionFunc(new Exception( - $"Could'nt authenticate client '{connectHostname}' with fake certificate.", e)); sslStream?.Dispose(); - return; + throw new ProxyConnectException( + $"Could'nt authenticate client '{connectHostname}' with fake certificate.", e, connectArgs); } if (await HttpHelper.IsConnectMethod(clientStream) == -1) @@ -282,21 +281,21 @@ await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); } - catch (ProxyHttpException e) + catch (ProxyException e) { - ExceptionFunc(e); + OnException(clientStream, e); } catch (IOException e) { - ExceptionFunc(new Exception("Connection was aborted", e)); + OnException(clientStream, new Exception("Connection was aborted", e)); } catch (SocketException e) { - ExceptionFunc(new Exception("Could not connect", e)); + OnException(clientStream, new Exception("Could not connect", e)); } catch (Exception e) { - ExceptionFunc(new Exception("Error occured in whilst handling the client", e)); + OnException(clientStream, new Exception("Error occured in whilst handling the client", e)); } finally { diff --git a/Titanium.Web.Proxy/Network/CertificateManager.cs b/Titanium.Web.Proxy/Network/CertificateManager.cs index d879a794f..57cabb9a3 100644 --- a/Titanium.Web.Proxy/Network/CertificateManager.cs +++ b/Titanium.Web.Proxy/Network/CertificateManager.cs @@ -327,10 +327,7 @@ private void InstallCertificate(StoreName storeName, StoreLocation storeLocation { if (RootCertificate == null) { - exceptionFunc( - new Exception("Could not install certificate" - + " as it is null or empty.")); - + exceptionFunc(new Exception("Could not install certificate as it is null or empty.")); return; } @@ -368,10 +365,7 @@ private void UninstallCertificate(StoreName storeName, StoreLocation storeLocati { if (certificate == null) { - exceptionFunc( - new Exception("Could not remove certificate" - + " as it is null or empty.")); - + exceptionFunc(new Exception("Could not remove certificate as it is null or empty.")); return; } diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index f02596ab8..8e813735e 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -7,6 +7,7 @@ using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; +using StreamExtended.Network; using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers.WinHttp; @@ -663,6 +664,18 @@ private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint) } } + private void OnException(CustomBufferedStream clientStream, Exception exception) + { +#if DEBUG + if (clientStream is DebugCustomBufferedStream debugStream) + { + debugStream.LogException(exception); + } +#endif + + ExceptionFunc(exception); + } + /// /// Quit listening on the given end point. /// diff --git a/Titanium.Web.Proxy/TransparentClientHandler.cs b/Titanium.Web.Proxy/TransparentClientHandler.cs index 283eba829..f2f86bd64 100644 --- a/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; @@ -8,6 +9,7 @@ using StreamExtended.Helpers; using StreamExtended.Network; using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Models; @@ -77,10 +79,9 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConn } catch (Exception e) { - ExceptionFunc(new Exception( - $"Could'nt authenticate client '{httpsHostName}' with fake certificate.", e)); sslStream?.Dispose(); - return; + throw new ProxyConnectException( + $"Could'nt authenticate client '{httpsHostName}' with fake certificate.", e, null); } } else @@ -127,6 +128,22 @@ await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, isHttps ? httpsHostName : null, null, true); } + catch (ProxyException e) + { + OnException(clientStream, e); + } + catch (IOException e) + { + OnException(clientStream, new Exception("Connection was aborted", e)); + } + catch (SocketException e) + { + OnException(clientStream, new Exception("Could not connect", e)); + } + catch (Exception e) + { + OnException(clientStream, new Exception("Error occured in whilst handling the client", e)); + } finally { clientStream.Dispose(); From 9f747316fded015ce2ca71379acbdd1f4590929b Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 1 May 2018 10:11:52 +0200 Subject: [PATCH 07/23] redundant parameter removed --- .../EventArguments/LimitedStream.cs | 2 +- .../EventArguments/SessionEventArgs.cs | 18 +++++++------- .../EventArguments/SessionEventArgsBase.cs | 4 ++-- Titanium.Web.Proxy/ExplicitClientHandler.cs | 5 ++-- .../Extensions/TcpExtensions.cs | 8 +++---- Titanium.Web.Proxy/RequestHandler.cs | 24 +++++++++---------- .../TransparentClientHandler.cs | 4 ++-- 7 files changed, 31 insertions(+), 34 deletions(-) diff --git a/Titanium.Web.Proxy/EventArguments/LimitedStream.cs b/Titanium.Web.Proxy/EventArguments/LimitedStream.cs index 3735bbdf5..c1fb7a02f 100644 --- a/Titanium.Web.Proxy/EventArguments/LimitedStream.cs +++ b/Titanium.Web.Proxy/EventArguments/LimitedStream.cs @@ -65,7 +65,7 @@ private void GetNextChunk() { bytesRemaining = -1; - //chunk trail + // chunk trail baseStream.ReadLineAsync().Wait(); } } diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs index 7970e21a7..3560e666d 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs @@ -88,14 +88,14 @@ private async Task ReadRequestBodyAsync(CancellationToken cancellationToken) var request = WebSession.Request; - //If not already read (not cached yet) + // If not already read (not cached yet) if (!request.IsBodyRead) { var body = await ReadBodyAsync(true, cancellationToken); request.Body = body; - //Now set the flag to true - //So that next time we can deliver body from cache + // Now set the flag to true + // So that next time we can deliver body from cache request.IsBodyRead = true; OnDataSent(body, 0, body.Length); } @@ -106,7 +106,7 @@ private async Task ReadRequestBodyAsync(CancellationToken cancellationToken) ///
    internal async Task ClearResponse(CancellationToken cancellationToken) { - //syphon out the response body from server + // syphon out the response body from server await SyphonOutBodyAsync(false, cancellationToken); WebSession.Response = new Response(); } @@ -139,14 +139,14 @@ private async Task ReadResponseBodyAsync(CancellationToken cancellationToken) return; } - //If not already read (not cached yet) + // If not already read (not cached yet) if (!response.IsBodyRead) { var body = await ReadBodyAsync(false, cancellationToken); response.Body = body; - //Now set the flag to true - //So that next time we can deliver body from cache + // Now set the flag to true + // So that next time we can deliver body from cache response.IsBodyRead = true; OnDataReceived(body, 0, body.Length); } @@ -196,7 +196,7 @@ internal async Task CopyRequestBodyAsync(HttpWriter writer, TransformationMode t long contentLength = request.ContentLength; - //send the request body bytes to server + // send the request body bytes to server if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData) { var reader = GetStreamReader(true); @@ -323,7 +323,7 @@ private async Task ReadUntilBoundaryAsync(ICustomStreamReader reader, long if (bufferDataLength == buffer.Length) { - //boundary is not longer than 70 bytes according to the specification, so keeping the last 100 (minimum 74) bytes is enough + // boundary is not longer than 70 bytes according to the specification, so keeping the last 100 (minimum 74) bytes is enough const int bytesToKeep = 100; Buffer.BlockCopy(buffer, buffer.Length - bytesToKeep, buffer, 0, bytesToKeep); bufferDataLength = bytesToKeep; diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index f8741bb3b..1729ca16a 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -53,14 +53,14 @@ protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, { var remoteEndPoint = ClientEndPoint; - //If client is localhost get the process id + // If client is localhost get the process id if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) { var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4; return TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port); } - //can't access process Id of remote request from remote machine + // can't access process Id of remote request from remote machine return -1; } diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index a24303c4f..266ebdae0 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -277,9 +277,8 @@ await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, } //Now create the request - await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, - clientStreamWriter, cancellationTokenSource, connectHostname, - connectArgs?.WebSession.ConnectRequest); + await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, + cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); } catch (ProxyException e) { diff --git a/Titanium.Web.Proxy/Extensions/TcpExtensions.cs b/Titanium.Web.Proxy/Extensions/TcpExtensions.cs index a76e49a16..8c3d78ea1 100644 --- a/Titanium.Web.Proxy/Extensions/TcpExtensions.cs +++ b/Titanium.Web.Proxy/Extensions/TcpExtensions.cs @@ -31,10 +31,10 @@ internal static void CloseSocket(this TcpClient tcpClient) try { - //This line is important! - //contributors please don't remove it without discussion - //It helps to avoid eventual deterioration of performance due to TCP port exhaustion - //due to default TCP CLOSE_WAIT timeout for 4 minutes + // This line is important! + // contributors please don't remove it without discussion + // It helps to avoid eventual deterioration of performance due to TCP port exhaustion + // due to default TCP CLOSE_WAIT timeout for 4 minutes if (socketCleanedUpGetter == null || !socketCleanedUpGetter(tcpClient.Client)) { tcpClient.LingerState = new LingerOption(true, 0); diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index eaf7e6102..0865cd1eb 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -44,8 +44,7 @@ partial class ProxyServer /// private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, - CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest, - bool isTransparentEndPoint = false) + CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest) { var cancellationToken = cancellationTokenSource.Token; TcpServerConnection serverConnection = null; @@ -123,20 +122,19 @@ await HeaderParser.ReadHeaders(clientStream, args.WebSession.Request.Headers, args.ProxyClient.ClientStream = clientStream; args.ProxyClient.ClientStreamWriter = clientStreamWriter; - //proxy authorization check - if (!args.IsTransparent && httpsConnectHostname == null && - await CheckAuthorization(args) == false) + if (!args.IsTransparent) { - await InvokeBeforeResponse(args); + //proxy authorization check + if (httpsConnectHostname == null && await CheckAuthorization(args) == false) + { + await InvokeBeforeResponse(args); - //send the response - await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, - cancellationToken: cancellationToken); - return; - } + //send the response + await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, + cancellationToken: cancellationToken); + return; + } - if (!isTransparentEndPoint) - { PrepareRequestHeaders(request.Headers); request.Host = request.RequestUri.Authority; } diff --git a/Titanium.Web.Proxy/TransparentClientHandler.cs b/Titanium.Web.Proxy/TransparentClientHandler.cs index f2f86bd64..e29530c46 100644 --- a/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -99,7 +99,7 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConn int available = clientStream.Available; if (available > 0) { - //send the buffered data + // send the buffered data var data = BufferPool.GetBuffer(BufferSize); try @@ -126,7 +126,7 @@ await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, //HTTPS server created - we can now decrypt the client's traffic //Now create the request await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, - cancellationTokenSource, isHttps ? httpsHostName : null, null, true); + cancellationTokenSource, isHttps ? httpsHostName : null, null); } catch (ProxyException e) { From 875ba62f7c7a552322b6adbd0a1048d9692b7c5f Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 1 May 2018 10:32:15 +0200 Subject: [PATCH 08/23] space between // and text in comments (except when it is a commented code) --- .../Program.cs | 4 +- .../ProxyTestController.cs | 111 ++++++++++-------- .../SslTests.cs | 16 +-- .../CertificateManagerTests.cs | 6 +- Titanium.Web.Proxy/CertificateHandler.cs | 12 +- Titanium.Web.Proxy/ExplicitClientHandler.cs | 26 ++-- Titanium.Web.Proxy/Helpers/HttpHelper.cs | 22 ++-- Titanium.Web.Proxy/Helpers/HttpWriter.cs | 8 +- Titanium.Web.Proxy/Helpers/SystemProxy.cs | 2 +- Titanium.Web.Proxy/Helpers/Tcp.cs | 6 +- Titanium.Web.Proxy/Http/HeaderCollection.cs | 2 +- Titanium.Web.Proxy/Http/HttpWebClient.cs | 22 ++-- Titanium.Web.Proxy/Http/Request.cs | 14 +-- .../Http/RequestResponseBase.cs | 2 +- Titanium.Web.Proxy/Http/Response.cs | 10 +- .../Http/Responses/GenericResponse.cs | 4 +- .../Network/Certificate/BCCertificateMaker.cs | 2 +- .../Certificate/WinCertificateMaker.cs | 18 +-- .../Network/CertificateManager.cs | 48 ++++---- .../Network/Tcp/TcpConnectionFactory.cs | 6 +- .../Network/WinAuth/Security/Common.cs | 34 +++--- .../Network/WinAuth/Security/Message.cs | 8 +- .../WinAuth/Security/WinAuthEndPoint.cs | 50 ++++---- .../ProxyAuthorizationHandler.cs | 8 +- Titanium.Web.Proxy/ProxyServer.cs | 14 +-- Titanium.Web.Proxy/RequestHandler.cs | 44 +++---- Titanium.Web.Proxy/ResponseHandler.cs | 20 ++-- .../TransparentClientHandler.cs | 10 +- Titanium.Web.Proxy/WinAuthHandler.cs | 29 ++--- 29 files changed, 291 insertions(+), 267 deletions(-) diff --git a/Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs b/Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs index 59afe278c..06fe4fce3 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs +++ b/Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs @@ -9,10 +9,10 @@ public class Program public static void Main(string[] args) { - //fix console hang due to QuickEdit mode + // fix console hang due to QuickEdit mode ConsoleHelper.DisableQuickEditMode(); - //Start proxy controller + // Start proxy controller controller.StartProxy(); Console.WriteLine("Hit any key to exit.."); diff --git a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs index 96a878a1b..1c2556a05 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs +++ b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs @@ -18,26 +18,26 @@ public class ProxyTestController private readonly ProxyServer proxyServer; - //keep track of request headers + // keep track of request headers private readonly IDictionary requestHeaderHistory = new ConcurrentDictionary(); - //keep track of response headers + // keep track of response headers private readonly IDictionary responseHeaderHistory = new ConcurrentDictionary(); private ExplicitProxyEndPoint explicitEndPoint; - //share requestBody outside handlers - //Using a dictionary is not a good idea since it can cause memory overflow - //ideally the data should be moved out of memory - //private readonly IDictionary requestBodyHistory = new ConcurrentDictionary(); + // share requestBody outside handlers + // Using a dictionary is not a good idea since it can cause memory overflow + // ideally the data should be moved out of memory + // private readonly IDictionary requestBodyHistory = new ConcurrentDictionary(); public ProxyTestController() { proxyServer = new ProxyServer(); - //generate root certificate without storing it in file system + // generate root certificate without storing it in file system //proxyServer.CertificateManager.CreateRootCertificate(false); //proxyServer.CertificateManager.TrustRootCertificate(); @@ -63,11 +63,12 @@ public ProxyTestController() }; proxyServer.ForwardToUpstreamGateway = true; proxyServer.CertificateManager.SaveFakeCertificates = true; - //optionally set the Certificate Engine - //Under Mono or Non-Windows runtimes only BouncyCastle will be supported + + // optionally set the Certificate Engine + // Under Mono or Non-Windows runtimes only BouncyCastle will be supported //proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle; - //optionally set the Root Certificate + // optionally set the Root Certificate //proxyServer.CertificateManager.RootCertificate = new X509Certificate2("myCert.pfx", string.Empty, X509KeyStorageFlags.Exportable); } @@ -83,27 +84,26 @@ public void StartProxy() explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000); - //Fired when a CONNECT request is received + // Fired when a CONNECT request is received explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse; - //An explicit endpoint is where the client knows about the existence of a proxy - //So client sends request in a proxy friendly manner + // An explicit endpoint is where the client knows about the existence of a proxy + // So client sends request in a proxy friendly manner proxyServer.AddEndPoint(explicitEndPoint); proxyServer.Start(); - //Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy) - //A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS - //to send data to this endPoint + // Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy) + // A transparent endpoint usually requires a network router port forwarding HTTP(S) packets or DNS + // to send data to this endPoint //var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 443, true) - //{ - // //Generic Certificate hostname to use - // //When SNI is disabled by client + //{ + // // Generic Certificate hostname to use + // // When SNI is disabled by client // GenericCertificateName = "google.com" //}; //proxyServer.AddEndPoint(transparentEndPoint); - //proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 }; //proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 }; @@ -117,7 +117,7 @@ public void StartProxy() if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) #endif { - //Only explicit proxies can be set as system proxy! + // Only explicit proxies can be set as system proxy! //proxyServer.SetAsSystemHttpProxy(explicitEndPoint); //proxyServer.SetAsSystemHttpsProxy(explicitEndPoint); proxyServer.SetAsSystemProxy(explicitEndPoint, ProxyProtocolType.AllHttp); @@ -135,8 +135,8 @@ public void Stop() proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection; proxyServer.Stop(); - - //remove the generated certificates + + // remove the generated certificates //proxyServer.CertificateManager.RemoveTrustedRootCertificates(); } @@ -147,9 +147,9 @@ private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSess if (hostname.Contains("dropbox.com")) { - //Exclude Https addresses you don't want to proxy - //Useful for clients that use certificate pinning - //for example dropbox.com + // Exclude Https addresses you don't want to proxy + // Useful for clients that use certificate pinning + // for example dropbox.com e.DecryptSsl = false; } } @@ -158,13 +158,13 @@ private async Task OnBeforeTunnelConnectResponse(object sender, TunnelConnectSes { } - //intecept & cancel redirect or update requests + // intecept & cancel redirect or update requests private async Task OnRequest(object sender, SessionEventArgs e) { WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount); WriteToConsole(e.WebSession.Request.Url); - //read request headers + // read request headers requestHeaderHistory[e.Id] = e.WebSession.Request.Headers; ////This sample shows how to get the multipart form data headers @@ -174,22 +174,22 @@ private async Task OnRequest(object sender, SessionEventArgs e) //} //if (e.WebSession.Request.HasBody) - //{ - // //Get/Set request body bytes + //{ + // // Get/Set request body bytes // var bodyBytes = await e.GetRequestBody(); // await e.SetRequestBody(bodyBytes); - // //Get/Set request body as string + // // Get/Set request body as string // string bodyString = await e.GetRequestBodyAsString(); // await e.SetRequestBodyString(bodyString); // //requestBodyHistory[e.Id] = bodyString; - //} + //} - //To cancel a request with a custom HTML content - //Filter URL + // To cancel a request with a custom HTML content + // Filter URL //if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("yahoo.com")) - //{ + //{ // e.Ok("" + // "

    " + // "Website Blocked" + @@ -197,16 +197,16 @@ private async Task OnRequest(object sender, SessionEventArgs e) // "

    Blocked by titanium web proxy.

    " + // "" + // ""); - //} + //} ////Redirect example //if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org")) - //{ + //{ // e.Redirect("https://www.paypal.com"); - //} + //} } - //Modify response + // Modify response private void MultipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e) { var session = (SessionEventArgs)sender; @@ -221,11 +221,30 @@ private async Task OnResponse(object sender, SessionEventArgs e) { WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount); + var ext = System.IO.Path.GetExtension(e.WebSession.Request.RequestUri.AbsolutePath); + + //if (ext == ".gif" || ext == ".png" || ext == ".jpg") + //{ + // byte[] btBody = Encoding.UTF8.GetBytes("" + + // "

    " + + // "Image is blocked" + + // "

    " + + // "

    Blocked by Titanium

    " + + // "" + + // ""); + + // var response = new OkResponse(btBody); + // response.HttpVersion = e.WebSession.Request.HttpVersion; + + // e.Respond(response); + // e.TerminateServerConnection(); + //} + //if (requestBodyHistory.ContainsKey(e.Id)) - //{ - // //access request body by looking up the shared dictionary using requestId + //{ + // // access request body by looking up the shared dictionary using requestId // var requestBody = requestBodyHistory[e.Id]; - //} + //} ////read response headers //responseHeaderHistory[e.Id] = e.WebSession.Response.Headers; @@ -235,7 +254,7 @@ private async Task OnResponse(object sender, SessionEventArgs e) ////if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return; //if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST") - //{ + //{ // if (e.WebSession.Response.StatusCode == (int)HttpStatusCode.OK) // { // if (e.WebSession.Response.ContentType != null && e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html")) @@ -247,7 +266,7 @@ private async Task OnResponse(object sender, SessionEventArgs e) // await e.SetResponseBodyString(body); // } // } - //} + //} } /// @@ -257,7 +276,7 @@ private async Task OnResponse(object sender, SessionEventArgs e) /// public 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 == SslPolicyErrors.None) { e.IsValid = true; @@ -273,7 +292,7 @@ public Task OnCertificateValidation(object sender, CertificateValidationEventArg /// public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e) { - //set e.clientCertificate to override + // set e.clientCertificate to override return Task.FromResult(0); } diff --git a/Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs b/Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs index e23061f32..2e8311592 100644 --- a/Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs +++ b/Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs @@ -17,8 +17,8 @@ public class SslTests //disable this test until CI is prepared to handle public void TestSsl() { - //expand this to stress test to find - //why in long run proxy becomes unresponsive as per issue #184 + // expand this to stress test to find + // why in long run proxy becomes unresponsive as per issue #184 string testUrl = "https://google.com"; int proxyPort = 8086; var proxy = new ProxyTestController(); @@ -62,8 +62,8 @@ public void StartProxy(int proxyPort) var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, proxyPort, true); - //An explicit endpoint is where the client knows about the existance of a proxy - //So client sends request in a proxy friendly manner + // An explicit endpoint is where the client knows about the existance of a proxy + // So client sends request in a proxy friendly manner proxyServer.AddEndPoint(explicitEndPoint); proxyServer.Start(); @@ -84,14 +84,14 @@ public void Stop() proxyServer.Stop(); } - //intecept & cancel, redirect or update requests + // intecept & cancel, redirect or update requests public async Task OnRequest(object sender, SessionEventArgs e) { Debug.WriteLine(e.WebSession.Request.Url); await Task.FromResult(0); } - //Modify response + // Modify response public async Task OnResponse(object sender, SessionEventArgs e) { await Task.FromResult(0); @@ -104,7 +104,7 @@ public async Task OnResponse(object sender, SessionEventArgs e) /// public 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 == SslPolicyErrors.None) { e.IsValid = true; @@ -120,7 +120,7 @@ public Task OnCertificateValidation(object sender, CertificateValidationEventArg /// public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e) { - //set e.clientCertificate to override + // set e.clientCertificate to override return Task.FromResult(0); } diff --git a/Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs b/Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs index 8735c08c5..15a464683 100644 --- a/Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs +++ b/Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs @@ -33,7 +33,7 @@ public async Task Simple_BC_Create_Certificate_Test() { tasks.AddRange(hostNames.Select(host => Task.Run(() => { - //get the connection + // get the connection var certificate = mgr.CreateCertificate(host, false); Assert.IsNotNull(certificate); }))); @@ -44,7 +44,7 @@ public async Task Simple_BC_Create_Certificate_Test() mgr.StopClearIdleCertificates(); } - //uncomment this to compare WinCert maker performance with BC (BC takes more time for same test above) + // uncomment this to compare WinCert maker performance with BC (BC takes more time for same test above) [TestMethod] public async Task Simple_Create_Win_Certificate_Test() { @@ -66,7 +66,7 @@ public async Task Simple_Create_Win_Certificate_Test() { tasks.AddRange(hostNames.Select(host => Task.Run(() => { - //get the connection + // get the connection var certificate = mgr.CreateCertificate(host, false); Assert.IsNotNull(certificate); }))); diff --git a/Titanium.Web.Proxy/CertificateHandler.cs b/Titanium.Web.Proxy/CertificateHandler.cs index 811a0d839..17fdc6d1c 100644 --- a/Titanium.Web.Proxy/CertificateHandler.cs +++ b/Titanium.Web.Proxy/CertificateHandler.cs @@ -19,7 +19,7 @@ public partial class ProxyServer internal bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { - //if user callback is registered then do it + // if user callback is registered then do it if (ServerCertificateValidationCallback != null) { var args = new CertificateValidationEventArgs @@ -29,7 +29,7 @@ internal bool ValidateServerCertificate(object sender, X509Certificate certifica SslPolicyErrors = sslPolicyErrors }; - //why is the sender null? + // why is the sender null? ServerCertificateValidationCallback.InvokeAsync(this, args, exceptionFunc).Wait(); return args.IsValid; } @@ -39,8 +39,8 @@ internal bool ValidateServerCertificate(object sender, X509Certificate certifica return true; } - //By default - //do not allow this client to communicate with unauthenticated servers. + // By default + // do not allow this client to communicate with unauthenticated servers. return false; } @@ -77,7 +77,7 @@ internal X509Certificate SelectClientCertificate(object sender, string targetHos clientCertificate = localCertificates[0]; } - //If user call back is registered + // If user call back is registered if (ClientCertificateSelectionCallback != null) { var args = new CertificateSelectionEventArgs @@ -89,7 +89,7 @@ internal X509Certificate SelectClientCertificate(object sender, string targetHos ClientCertificate = clientCertificate }; - //why is the sender null? + // why is the sender null? ClientCertificateSelectionCallback.InvokeAsync(this, args, exceptionFunc).Wait(); return args.ClientCertificate; } diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index 266ebdae0..2dd97eefe 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -43,10 +43,10 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect string connectHostname = 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) { - //read the first line HTTP command + // read the first line HTTP command string httpCmd = await clientStream.ReadLineAsync(cancellationToken); if (string.IsNullOrEmpty(httpCmd)) { @@ -74,7 +74,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc); - //filter out excluded host names + // filter out excluded host names bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl; if (connectArgs.DenyConnect) @@ -89,7 +89,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect }; } - //send the response + // send the response await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, cancellationToken: cancellationToken); return; @@ -99,13 +99,13 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, { await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc); - //send the response + // send the response await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, cancellationToken: cancellationToken); return; } - //write back successfull CONNECT response + // write back successfull CONNECT response var response = ConnectResponse.CreateSuccessfullConnectResponse(version); // Set ContentLength explicitly to properly handle HTTP 1.0 @@ -153,7 +153,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, var certificate = endPoint.GenericCertificate ?? await CertificateManager.CreateCertificateAsync(certName); - //Successfully managed to authenticate the client using the fake certificate + // Successfully managed to authenticate the client using the fake certificate var options = new SslServerAuthenticationOptions(); if (http2Supproted) { @@ -170,7 +170,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck; await sslStream.AuthenticateAsServerAsync(options, cancellationToken); - //HTTPS server created - we can now decrypt the client's traffic + // HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); @@ -193,10 +193,10 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, throw new Exception("Session was terminated by user."); } - //Hostname is excluded or it is not an HTTPS connect + // Hostname is excluded or it is not an HTTPS connect if (!decryptSsl || !isClientHello) { - //create new connection + // create new connection using (var connection = await GetServerConnection(connectArgs, true, cancellationToken)) { if (isClientHello) @@ -204,7 +204,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, int available = clientStream.Available; if (available > 0) { - //send the buffered data + // send the buffered data var data = BufferPool.GetBuffer(BufferSize); try @@ -260,7 +260,7 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); } - //create new connection + // create new connection using (var connection = await GetServerConnection(connectArgs, true, cancellationToken)) { await connection.StreamWriter.WriteLineAsync("PRI * HTTP/2.0", cancellationToken); @@ -276,7 +276,7 @@ await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, } } - //Now create the request + // Now create the request await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); } diff --git a/Titanium.Web.Proxy/Helpers/HttpHelper.cs b/Titanium.Web.Proxy/Helpers/HttpHelper.cs index 7b3269ce9..e24717198 100644 --- a/Titanium.Web.Proxy/Helpers/HttpHelper.cs +++ b/Titanium.Web.Proxy/Helpers/HttpHelper.cs @@ -21,13 +21,13 @@ internal static Encoding GetEncodingFromContentType(string contentType) { try { - //return default if not specified + // return default if not specified if (contentType == null) { return defaultEncoding; } - //extract the encoding by finding the charset + // extract the encoding by finding the charset var parameters = contentType.Split(ProxyConstants.SemiColonSplit); foreach (string parameter in parameters) { @@ -51,11 +51,11 @@ internal static Encoding GetEncodingFromContentType(string contentType) } catch { - //parsing errors + // parsing errors // ignored } - //return default if not specified + // return default if not specified return defaultEncoding; } @@ -63,7 +63,7 @@ internal static string GetBoundaryFromContentType(string contentType) { if (contentType != null) { - //extract the boundary + // extract the boundary var parameters = contentType.Split(ProxyConstants.SemiColonSplit); foreach (string parameter in parameters) { @@ -81,7 +81,7 @@ internal static string GetBoundaryFromContentType(string contentType) } } - //return null if not specified + // return null if not specified return null; } @@ -94,14 +94,14 @@ internal static string GetBoundaryFromContentType(string contentType) /// internal static string GetWildCardDomainName(string hostname) { - //only for subdomains we need wild card - //example www.google.com or gstatic.google.com - //but NOT for google.com + // only for subdomains we need wild card + // example www.google.com or gstatic.google.com + // but NOT for google.com if (hostname.Split(ProxyConstants.DotSplit).Length > 2) { int idx = hostname.IndexOf(ProxyConstants.DotSplit); - //issue #352 + // issue #352 if (hostname.Substring(0, idx).Contains("-")) { return hostname; @@ -111,7 +111,7 @@ internal static string GetWildCardDomainName(string hostname) return "*." + rootDomain; } - //return as it is + // return as it is return hostname; } diff --git a/Titanium.Web.Proxy/Helpers/HttpWriter.cs b/Titanium.Web.Proxy/Helpers/HttpWriter.cs index 0938658a5..322701f52 100644 --- a/Titanium.Web.Proxy/Helpers/HttpWriter.cs +++ b/Titanium.Web.Proxy/Helpers/HttpWriter.cs @@ -165,19 +165,19 @@ internal Task WriteBodyAsync(byte[] data, bool isChunked, CancellationToken canc internal Task CopyBodyAsync(ICustomStreamReader streamReader, bool isChunked, long contentLength, Action onCopy, CancellationToken cancellationToken) { - //For chunked request we need to read data as they arrive, until we reach a chunk end symbol + // For chunked request we need to read data as they arrive, until we reach a chunk end symbol if (isChunked) { return CopyBodyChunkedAsync(streamReader, onCopy, cancellationToken); } - //http 1.0 or the stream reader limits the stream + // http 1.0 or the stream reader limits the stream if (contentLength == -1) { contentLength = long.MaxValue; } - //If not chunked then its easy just read the amount of bytes mentioned in content length header + // If not chunked then its easy just read the amount of bytes mentioned in content length header return CopyBytesFromStream(streamReader, contentLength, onCopy, cancellationToken); } @@ -230,7 +230,7 @@ private async Task CopyBodyChunkedAsync(ICustomStreamReader reader, Action(); cancellationTokenSource.Token.Register(() => taskCompletionSource.TrySetResult(true)); - //Now async relay all server=>client & client=>server data + // Now async relay all server=>client & client=>server data var clientBuffer = BufferPool.GetBuffer(bufferSize); var serverBuffer = BufferPool.GetBuffer(bufferSize); try @@ -217,7 +217,7 @@ private static async Task SendRawTap(Stream clientStream, Stream serverStream, i CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc) { - //Now async relay all server=>client & client=>server data + // Now async relay all server=>client & client=>server data var sendRelay = clientStream.CopyToAsync(serverStream, onDataSend, bufferSize, cancellationTokenSource.Token); var receiveRelay = @@ -273,7 +273,7 @@ internal static async Task SendHttp2(Stream clientStream, Stream serverStream, i CancellationTokenSource cancellationTokenSource, Guid connectionId, ExceptionHandler exceptionFunc) { - //Now async relay all server=>client & client=>server data + // Now async relay all server=>client & client=>server data var sendRelay = CopyHttp2FrameAsync(clientStream, serverStream, onDataSend, bufferSize, connectionId, cancellationTokenSource.Token); diff --git a/Titanium.Web.Proxy/Http/HeaderCollection.cs b/Titanium.Web.Proxy/Http/HeaderCollection.cs index 84220b5ec..c233542b8 100644 --- a/Titanium.Web.Proxy/Http/HeaderCollection.cs +++ b/Titanium.Web.Proxy/Http/HeaderCollection.cs @@ -296,7 +296,7 @@ internal void SetOrAddHeaderValue(string headerName, string value) /// internal void FixProxyHeaders() { - //If proxy-connection close was returned inform to close the connection + // If proxy-connection close was returned inform to close the connection string proxyHeader = GetHeaderValueOrNull(KnownHeaders.ProxyConnection); RemoveHeader(KnownHeaders.ProxyConnection); diff --git a/Titanium.Web.Proxy/Http/HttpWebClient.cs b/Titanium.Web.Proxy/Http/HttpWebClient.cs index c3edf87a3..cd0409671 100644 --- a/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -89,13 +89,13 @@ internal async Task SendRequest(bool enable100ContinueBehaviour, bool isTranspar var writer = ServerConnection.StreamWriter; - //prepare the request & headers + // prepare the request & headers await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery, Request.HttpVersion), cancellationToken); - //Send Authentication to Upstream proxy if needed + // Send Authentication to Upstream proxy if needed if (!isTransparent && upstreamProxy != null && ServerConnection.IsHttps == false && !string.IsNullOrEmpty(upstreamProxy.UserName) @@ -106,7 +106,7 @@ await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamPro .WriteToStreamAsync(writer, cancellationToken); } - //write request headers + // write request headers foreach (var header in Request.Headers) { if (isTransparent || header.Name != KnownHeaders.ProxyAuthorization) @@ -126,7 +126,7 @@ await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamPro Response.ParseResponseLine(httpStatus, out _, out int responseStatusCode, out string responseStatusDescription); - //find if server is willing for expect continue + // find if server is willing for expect continue if (responseStatusCode == (int)HttpStatusCode.Continue && responseStatusDescription.EqualsIgnoreCase("continue")) { @@ -149,7 +149,7 @@ await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamPro /// internal async Task ReceiveResponse(CancellationToken cancellationToken) { - //return if this is already read + // return if this is already read if (Response.StatusCode != 0) { return; @@ -172,16 +172,16 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) Response.StatusCode = statusCode; Response.StatusDescription = statusDescription; - //For HTTP 1.1 comptibility server may send expect-continue even if not asked for it in request + // For HTTP 1.1 comptibility server may send expect-continue even if not asked for it in request if (Response.StatusCode == (int)HttpStatusCode.Continue && Response.StatusDescription.EqualsIgnoreCase("continue")) { - //Read the next line after 100-continue + // Read the next line after 100-continue Response.Is100Continue = true; Response.StatusCode = 0; await ServerConnection.Stream.ReadLineAsync(cancellationToken); - //now receive response + // now receive response await ReceiveResponse(cancellationToken); return; } @@ -189,17 +189,17 @@ internal async Task ReceiveResponse(CancellationToken cancellationToken) if (Response.StatusCode == (int)HttpStatusCode.ExpectationFailed && Response.StatusDescription.EqualsIgnoreCase("expectation failed")) { - //read next line after expectation failed response + // read next line after expectation failed response Response.ExpectationFailed = true; Response.StatusCode = 0; await ServerConnection.Stream.ReadLineAsync(cancellationToken); - //now receive response + // now receive response await ReceiveResponse(cancellationToken); return; } - //Read the response headers in to unique and non-unique header collections + // Read the response headers in to unique and non-unique header collections await HeaderParser.ReadHeaders(ServerConnection.Stream, Response.Headers, cancellationToken); } diff --git a/Titanium.Web.Proxy/Http/Request.cs b/Titanium.Web.Proxy/Http/Request.cs index 8c9effeb5..d67228626 100644 --- a/Titanium.Web.Proxy/Http/Request.cs +++ b/Titanium.Web.Proxy/Http/Request.cs @@ -43,19 +43,19 @@ public override bool HasBody { long contentLength = ContentLength; - //If content length is set to 0 the request has no body + // If content length is set to 0 the request has no body if (contentLength == 0) { return false; } - //Has body only if request is chunked or content length >0 + // Has body only if request is chunked or content length >0 if (IsChunked || contentLength > 0) { return true; } - //has body if POST and when version is http/1.0 + // has body if POST and when version is http/1.0 if (Method == "POST" && HttpVersion == HttpHeader.Version10) { return true; @@ -157,7 +157,7 @@ internal override void EnsureBodyAvailable(bool throwWhenNotReadYet = true) return; } - //GET request don't have a request body to read + // GET request don't have a request body to read if (!HasBody) { throw new BodyNotFoundException("Request don't have a body. " + @@ -189,7 +189,7 @@ internal static string CreateRequestLine(string httpMethod, string httpUrl, Vers internal static void ParseRequestLine(string httpCmd, out string httpMethod, out string httpUrl, out Version version) { - //break up the line into three components (method, remote URL & Http Version) + // break up the line into three components (method, remote URL & Http Version) var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3); if (httpCmdSplit.Length < 2) @@ -197,7 +197,7 @@ internal static void ParseRequestLine(string httpCmd, out string httpMethod, out throw new Exception("Invalid HTTP request line: " + httpCmd); } - //Find the request Verb + // Find the request Verb httpMethod = httpCmdSplit[0]; if (!IsAllUpper(httpMethod)) { @@ -206,7 +206,7 @@ internal static void ParseRequestLine(string httpCmd, out string httpMethod, out httpUrl = httpCmdSplit[1]; - //parse the HTTP version + // parse the HTTP version version = HttpHeader.Version11; if (httpCmdSplit.Length == 3) { diff --git a/Titanium.Web.Proxy/Http/RequestResponseBase.cs b/Titanium.Web.Proxy/Http/RequestResponseBase.cs index d00c7de0a..6fe6878cf 100644 --- a/Titanium.Web.Proxy/Http/RequestResponseBase.cs +++ b/Titanium.Web.Proxy/Http/RequestResponseBase.cs @@ -140,7 +140,7 @@ internal set BodyInternal = value; bodyString = null; - //If there is a content length header update it + // If there is a content length header update it UpdateContentLength(); } } diff --git a/Titanium.Web.Proxy/Http/Response.cs b/Titanium.Web.Proxy/Http/Response.cs index 1bb5d9f46..650292cda 100644 --- a/Titanium.Web.Proxy/Http/Response.cs +++ b/Titanium.Web.Proxy/Http/Response.cs @@ -47,21 +47,21 @@ public override bool HasBody { long contentLength = ContentLength; - //If content length is set to 0 the response has no body + // If content length is set to 0 the response has no body if (contentLength == 0) { return false; } - //Has body only if response is chunked or content length >0 - //If none are true then check if connection:close header exist, if so write response until server or client terminates the connection + // Has body only if response is chunked or content length >0 + // If none are true then check if connection:close header exist, if so write response until server or client terminates the connection if (IsChunked || contentLength > 0 || !KeepAlive) { return true; } - //has response if connection:keep-alive header exist and when version is http/1.0 - //Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream) + // has response if connection:keep-alive header exist and when version is http/1.0 + // Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream) if (KeepAlive && HttpVersion == HttpHeader.Version10) { return true; diff --git a/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs b/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs index e4da775de..0646d83d9 100644 --- a/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs +++ b/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs @@ -19,8 +19,8 @@ public GenericResponse(HttpStatusCode status) #if NET45 StatusDescription = HttpWorkerRequest.GetStatusDescription(StatusCode); #else - //todo: this is not really correct, status description should contain spaces, too - //see: https://tools.ietf.org/html/rfc7231#section-6.1 + // todo: this is not really correct, status description should contain spaces, too + // see: https://tools.ietf.org/html/rfc7231#section-6.1 StatusDescription = status.ToString(); #endif } diff --git a/Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs b/Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs index 0736d89b3..d3a060b12 100644 --- a/Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs +++ b/Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs @@ -95,7 +95,7 @@ private static X509Certificate2 GenerateCertificate(string hostName, if (hostName != null) { - //add subject alternative names + // add subject alternative names var subjectAlternativeNames = new Asn1Encodable[] { new GeneralName(GeneralName.DnsName, hostName) }; var subjectAlternativeNamesExtension = new DerSequence(subjectAlternativeNames); diff --git a/Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs b/Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs index c2357d163..2ece4e41a 100644 --- a/Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs +++ b/Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs @@ -64,7 +64,7 @@ internal WinCertificateMaker(ExceptionHandler exceptionFunc) typeSignerCertificate = Type.GetTypeFromProgID("X509Enrollment.CSignerCertificate"); typeX509Enrollment = Type.GetTypeFromProgID("X509Enrollment.CX509Enrollment"); - //for alternative names + // for alternative names typeAltNamesCollection = Type.GetTypeFromProgID("X509Enrollment.CAlternativeNames"); typeExtNames = Type.GetTypeFromProgID("X509Enrollment.CX509ExtensionAlternativeNames"); typeCAlternativeName = Type.GetTypeFromProgID("X509Enrollment.CAlternativeName"); @@ -192,7 +192,7 @@ private X509Certificate2 MakeCertificate(bool isRoot, string subject, string ful if (!isRoot) { - //add alternative names + // add alternative names // https://forums.iis.net/t/1180823.aspx var altNameCollection = Activator.CreateInstance(typeAltNamesCollection); @@ -284,15 +284,19 @@ private X509Certificate2 MakeCertificateInternal(string sSubjectCN, bool isRoot, cancellationToken).Result; } - //Subject + // Subject string fullSubject = $"CN={sSubjectCN}"; - //Sig Algo + + // Sig Algo const string hashAlgo = "SHA256"; - //Grace Days + + // Grace Days const int graceDays = -366; - //ValiDays + + // ValiDays const int validDays = 1825; - //KeyLength + + // KeyLength const int keyLength = 2048; var graceTime = DateTime.Now.AddDays(graceDays); diff --git a/Titanium.Web.Proxy/Network/CertificateManager.cs b/Titanium.Web.Proxy/Network/CertificateManager.cs index 57cabb9a3..12607b045 100644 --- a/Titanium.Web.Proxy/Network/CertificateManager.cs +++ b/Titanium.Web.Proxy/Network/CertificateManager.cs @@ -141,7 +141,7 @@ public CertificateEngine CertificateEngine get => engine; set { - //For Mono (or Non-Windows) only Bouncy Castle is supported + // For Mono (or Non-Windows) only Bouncy Castle is supported if (!RunTime.IsWindows || RunTime.IsRunningOnMono) { value = CertificateEngine.BouncyCastle; @@ -333,8 +333,8 @@ private void InstallCertificate(StoreName storeName, StoreLocation storeLocation var x509Store = new X509Store(storeName, storeLocation); - //TODO - //also it should do not duplicate if certificate already exists + // todo + // also it should do not duplicate if certificate already exists try { x509Store.Open(OpenFlags.ReadWrite); @@ -428,7 +428,7 @@ internal X509Certificate2 CreateCertificate(string certificateName, bool isRootC { certificate = MakeCertificate(certificateName, false); - //store as cache + // store as cache Task.Run(() => { try @@ -447,7 +447,7 @@ internal X509Certificate2 CreateCertificate(string certificateName, bool isRootC { certificate = new X509Certificate2(certificatePath, string.Empty, StorageFlag); } - //if load failed create again + // if load failed create again catch { certificate = MakeCertificate(certificateName, false); @@ -474,21 +474,21 @@ internal X509Certificate2 CreateCertificate(string certificateName, bool isRootC /// internal async Task CreateCertificateAsync(string certificateName) { - //check in cache first + // check in cache first if (certificateCache.TryGetValue(certificateName, out var cached)) { cached.LastAccess = DateTime.Now; return cached.Certificate; } - //handle burst requests with same certificate name - //by checking for existing task for same certificate name + // handle burst requests with same certificate name + // by checking for existing task for same certificate name if (pendingCertificateCreationTasks.TryGetValue(certificateName, out var task)) { return await task; } - //run certificate creation task & add it to pending tasks + // run certificate creation task & add it to pending tasks task = Task.Run(() => { var result = CreateCertificate(certificateName, false); @@ -504,7 +504,7 @@ internal async Task CreateCertificateAsync(string certificateN }); pendingCertificateCreationTasks.TryAdd(certificateName, task); - //cleanup pending tasks & return result + // cleanup pending tasks & return result var certificate = await task; pendingCertificateCreationTasks.TryRemove(certificateName, out task); @@ -528,7 +528,7 @@ internal async void ClearIdleCertificates() certificateCache.TryRemove(cache.Key, out _); } - //after a minute come back to check for outdated certificates in cache + // after a minute come back to check for outdated certificates in cache await Task.Delay(1000 * 60); } } @@ -659,20 +659,20 @@ public bool LoadRootCertificate(string pfxFilePath, string password, bool overwr ///
    public void TrustRootCertificate(bool machineTrusted = false) { - //currentUser\personal + // currentUser\personal InstallCertificate(StoreName.My, StoreLocation.CurrentUser); if (!machineTrusted) { - //currentUser\Root + // currentUser\Root InstallCertificate(StoreName.Root, StoreLocation.CurrentUser); } else { - //current system + // current system InstallCertificate(StoreName.My, StoreLocation.LocalMachine); - //this adds to both currentUser\Root & currentMachine\Root + // this adds to both currentUser\Root & currentMachine\Root InstallCertificate(StoreName.Root, StoreLocation.LocalMachine); } } @@ -689,13 +689,13 @@ public bool TrustRootCertificateAsAdmin(bool machineTrusted = false) return false; } - //currentUser\Personal + // currentUser\Personal InstallCertificate(StoreName.My, StoreLocation.CurrentUser); string pfxFileName = Path.GetTempFileName(); File.WriteAllBytes(pfxFileName, RootCertificate.Export(X509ContentType.Pkcs12, PfxPassword)); - //currentUser\Root, currentMachine\Personal & currentMachine\Root + // currentUser\Root, currentMachine\Personal & currentMachine\Root var info = new ProcessStartInfo { FileName = "certutil.exe", @@ -804,20 +804,20 @@ public bool IsRootCertificateMachineTrusted() /// Should also remove from machine store? public void RemoveTrustedRootCertificate(bool machineTrusted = false) { - //currentUser\personal + // currentUser\personal UninstallCertificate(StoreName.My, StoreLocation.CurrentUser, RootCertificate); if (!machineTrusted) { - //currentUser\Root + // currentUser\Root UninstallCertificate(StoreName.Root, StoreLocation.CurrentUser, RootCertificate); } else { - //current system + // current system UninstallCertificate(StoreName.My, StoreLocation.LocalMachine, RootCertificate); - //this adds to both currentUser\Root & currentMachine\Root + // this adds to both currentUser\Root & currentMachine\Root UninstallCertificate(StoreName.Root, StoreLocation.LocalMachine, RootCertificate); } } @@ -833,7 +833,7 @@ public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false) return false; } - //currentUser\Personal + // currentUser\Personal UninstallCertificate(StoreName.My, StoreLocation.CurrentUser, RootCertificate); var infos = new List(); @@ -855,7 +855,7 @@ public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false) infos.AddRange( new List { - //currentMachine\Personal + // currentMachine\Personal new ProcessStartInfo { FileName = "certutil.exe", @@ -866,7 +866,7 @@ public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false) ErrorDialog = false, WindowStyle = ProcessWindowStyle.Hidden }, - //currentUser\Personal & currentMachine\Personal + // currentUser\Personal & currentMachine\Personal new ProcessStartInfo { FileName = "certutil.exe", diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs index 82d09663d..0b430b236 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs @@ -39,13 +39,13 @@ internal async Task CreateClient(string remoteHostName, int { bool useUpstreamProxy = false; - //check if external proxy is set for HTTP/HTTPS + // check if external proxy is set for HTTP/HTTPS if (externalProxy != null && !(externalProxy.HostName == remoteHostName && externalProxy.Port == remotePort)) { useUpstreamProxy = true; - //check if we need to ByPass + // check if we need to ByPass if (externalProxy.BypassLocalhost && NetworkHelper.IsLocalIpAddress(remoteHostName)) { useUpstreamProxy = false; @@ -61,7 +61,7 @@ internal async Task CreateClient(string remoteHostName, int { tcpClient = new TcpClient(upStreamEndPoint); - //If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections + // If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections if (useUpstreamProxy) { await tcpClient.ConnectAsync(externalProxy.HostName, externalProxy.Port); diff --git a/Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs b/Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs index 180debd2e..3ffbc0108 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs @@ -173,7 +173,7 @@ internal struct SecurityBufferDesciption : IDisposable { internal int ulVersion; internal int cBuffers; - internal IntPtr pBuffers; //Point to SecBuffer + internal IntPtr pBuffers; // Point to SecBuffer internal SecurityBufferDesciption(int bufferSize) { @@ -206,12 +206,12 @@ public void Dispose() { for (int index = 0; index < cBuffers; index++) { - //The bits were written out the following order: - //int cbBuffer; - //int BufferType; - //pvBuffer; + // The bits were written out the following order: + // int cbBuffer; + // int BufferType; + // pvBuffer; //What we need to do here is to grab a hold of the pvBuffer allocate by the individual - //SecBuffer and release it... + // SecBuffer and release it... int currentOffset = index * Marshal.SizeOf(typeof(Buffer)); var secBufferpvBuffer = Marshal.ReadIntPtr(pBuffers, currentOffset + Marshal.SizeOf(typeof(int)) + Marshal.SizeOf(typeof(int))); @@ -249,11 +249,11 @@ internal byte[] GetBytes() for (int index = 0; index < cBuffers; index++) { - //The bits were written out the following order: - //int cbBuffer; - //int BufferType; - //pvBuffer; - //What we need to do here calculate the total number of bytes we need to copy... + // The bits were written out the following order: + // int cbBuffer; + // int BufferType; + // pvBuffer; + // What we need to do here calculate the total number of bytes we need to copy... int currentOffset = index * Marshal.SizeOf(typeof(Buffer)); bytesToAllocate += Marshal.ReadInt32(pBuffers, currentOffset); } @@ -262,12 +262,12 @@ internal byte[] GetBytes() for (int index = 0, bufferIndex = 0; index < cBuffers; index++) { - //The bits were written out the following order: - //int cbBuffer; - //int BufferType; - //pvBuffer; - //Now iterate over the individual buffers and put them together into a - //byte array... + // The bits were written out the following order: + // int cbBuffer; + // int BufferType; + // pvBuffer; + // Now iterate over the individual buffers and put them together into a + // byte array... int currentOffset = index * Marshal.SizeOf(typeof(Buffer)); int bytesToCopy = Marshal.ReadInt32(pBuffers, currentOffset); var secBufferpvBuffer = Marshal.ReadIntPtr(pBuffers, diff --git a/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs b/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs index a7c0148a5..125a0b29b 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs @@ -69,25 +69,25 @@ private void Decode(byte[] message) if (message == null) { - throw new ArgumentNullException("message"); + throw new ArgumentNullException(nameof(message)); } if (message.Length < 12) { string msg = "Minimum Type3 message length is 12 bytes."; - throw new ArgumentOutOfRangeException("message", message.Length, msg); + throw new ArgumentOutOfRangeException(nameof(message), message.Length, msg); } if (!CheckHeader(message)) { string msg = "Invalid Type3 message header."; - throw new ArgumentException(msg, "message"); + throw new ArgumentException(msg, nameof(message)); } if (LittleEndian.ToUInt16(message, 56) != message.Length) { string msg = "Invalid Type3 message length."; - throw new ArgumentException(msg, "message"); + throw new ArgumentException(msg, nameof(message)); } if (message.Length >= 64) diff --git a/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs b/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs index 98790a95a..20fa4e261 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs @@ -31,7 +31,7 @@ internal static byte[] AcquireInitialSecurityToken(string hostname, string authS { byte[] token; - //null for initial call + // null for initial call var serverToken = new SecurityBufferDesciption(); var clientToken = new SecurityBufferDesciption(MaximumTokenSize); @@ -99,7 +99,7 @@ internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverC { byte[] token; - //user server challenge + // user server challenge var serverToken = new SecurityBufferDesciption(serverChallenge); var clientToken = new SecurityBufferDesciption(MaximumTokenSize); @@ -156,7 +156,7 @@ internal static async void ClearIdleStates(int stateCacheTimeOutMinutes) authStates.Remove(cache.Key); } - //after a minute come back to check for outdated certificates in cache + // after a minute come back to check for outdated certificates in cache await Task.Delay(1000 * 60); } @@ -206,44 +206,44 @@ internal static void AuthenticatedResponse(Guid requestId) #region Native calls to secur32.dll [DllImport("secur32.dll", SetLastError = true)] - private static extern int InitializeSecurityContext(ref SecurityHandle phCredential, //PCredHandle - IntPtr phContext, //PCtxtHandle + private static extern int InitializeSecurityContext(ref SecurityHandle phCredential, // PCredHandle + IntPtr phContext, // PCtxtHandle string pszTargetName, int fContextReq, int reserved1, int targetDataRep, - ref SecurityBufferDesciption pInput, //PSecBufferDesc SecBufferDesc + ref SecurityBufferDesciption pInput, // PSecBufferDesc SecBufferDesc int reserved2, - out SecurityHandle phNewContext, //PCtxtHandle - out SecurityBufferDesciption pOutput, //PSecBufferDesc SecBufferDesc - out uint pfContextAttr, //managed ulong == 64 bits!!! - out SecurityInteger ptsExpiry); //PTimeStamp + out SecurityHandle phNewContext, // PCtxtHandle + out SecurityBufferDesciption pOutput, // PSecBufferDesc SecBufferDesc + out uint pfContextAttr, // managed ulong == 64 bits!!! + out SecurityInteger ptsExpiry); // PTimeStamp [DllImport("secur32", CharSet = CharSet.Auto, SetLastError = true)] - private static extern int InitializeSecurityContext(ref SecurityHandle phCredential, //PCredHandle - ref SecurityHandle phContext, //PCtxtHandle + private static extern int InitializeSecurityContext(ref SecurityHandle phCredential, // PCredHandle + ref SecurityHandle phContext, // PCtxtHandle string pszTargetName, int fContextReq, int reserved1, int targetDataRep, - ref SecurityBufferDesciption secBufferDesc, //PSecBufferDesc SecBufferDesc + ref SecurityBufferDesciption secBufferDesc, // PSecBufferDesc SecBufferDesc int reserved2, - out SecurityHandle phNewContext, //PCtxtHandle - out SecurityBufferDesciption pOutput, //PSecBufferDesc SecBufferDesc - out uint pfContextAttr, //managed ulong == 64 bits!!! - out SecurityInteger ptsExpiry); //PTimeStamp + out SecurityHandle phNewContext, // PCtxtHandle + out SecurityBufferDesciption pOutput, // PSecBufferDesc SecBufferDesc + out uint pfContextAttr, // managed ulong == 64 bits!!! + out SecurityInteger ptsExpiry); // PTimeStamp [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = false)] private static extern int AcquireCredentialsHandle( - string pszPrincipal, //SEC_CHAR* - string pszPackage, //SEC_CHAR* //"Kerberos","NTLM","Negotiative" + string pszPrincipal, // SEC_CHAR* + string pszPackage, // SEC_CHAR* // "Kerberos","NTLM","Negotiative" int fCredentialUse, - IntPtr pAuthenticationId, //_LUID AuthenticationID,//pvLogonID, //PLUID - IntPtr pAuthData, //PVOID - int pGetKeyFn, //SEC_GET_KEY_FN - IntPtr pvGetKeyArgument, //PVOID - ref SecurityHandle phCredential, //SecHandle //PCtxtHandle ref - ref SecurityInteger ptsExpiry); //PTimeStamp //TimeStamp ref + IntPtr pAuthenticationId, // _LUID AuthenticationID,//pvLogonID, // PLUID + IntPtr pAuthData, // PVOID + int pGetKeyFn, // SEC_GET_KEY_FN + IntPtr pvGetKeyArgument, // PVOID + ref SecurityHandle phCredential, // SecHandle // PCtxtHandle ref + ref SecurityInteger ptsExpiry); // PTimeStamp // TimeStamp ref #endregion } diff --git a/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs b/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs index 34a7ee99b..c1e75d830 100644 --- a/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs +++ b/Titanium.Web.Proxy/ProxyAuthorizationHandler.cs @@ -20,7 +20,7 @@ public partial class ProxyServer /// True if authorized. private async Task CheckAuthorization(SessionEventArgsBase session) { - //If we are not authorizing clients return true + // If we are not authorizing clients return true if (AuthenticateUserFunc == null) { return true; @@ -41,7 +41,7 @@ private async Task CheckAuthorization(SessionEventArgsBase session) if (headerValueParts.Length != 2 || !headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic)) { - //Return not authorized + // Return not authorized session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); return false; } @@ -50,7 +50,7 @@ private async Task CheckAuthorization(SessionEventArgsBase session) int colonIndex = decoded.IndexOf(':'); if (colonIndex == -1) { - //Return not authorized + // Return not authorized session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); return false; } @@ -70,7 +70,7 @@ private async Task CheckAuthorization(SessionEventArgsBase session) ExceptionFunc(new ProxyAuthorizationException("Error whilst authorizing request", session, e, httpHeaders)); - //Return not authorized + // Return not authorized session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); return false; } diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index 8e813735e..e581706f3 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -92,7 +92,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) { - //default values + // default values ConnectionTimeOutSeconds = 60; ProxyEndPoints = new List(); @@ -357,7 +357,7 @@ public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType p { CertificateManager.EnsureRootCertificate(); - //If certificate was trusted by the machine + // If certificate was trusted by the machine if (!CertificateManager.CertValidated) { protocolType = protocolType & ~ProxyProtocolType.Https; @@ -365,7 +365,7 @@ public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType p } } - //clear any settings previously added + // clear any settings previously added if (isHttp) { ProxyEndPoints.OfType().ToList().ForEach(x => x.IsSystemHttpProxy = false); @@ -472,8 +472,8 @@ public void Start() CertificateManager.EnsureRootCertificate(); } - //clear any system proxy settings which is pointing to our own endpoint (causing a cycle) - //due to non gracious proxy shutdown before or something else + // clear any system proxy settings which is pointing to our own endpoint (causing a cycle) + // due to non gracious proxy shutdown before or something else if (systemProxySettingsManager != null && RunTime.IsWindows) { var proxyInfo = systemProxySettingsManager.GetProxyInfoFromRegistry(); @@ -622,7 +622,7 @@ private void OnAcceptConnection(IAsyncResult asyn) try { - //based on end point type call appropriate request handlers + // based on end point type call appropriate request handlers tcpClient = endPoint.Listener.EndAcceptTcpClient(asyn); } catch (ObjectDisposedException) @@ -634,7 +634,7 @@ private void OnAcceptConnection(IAsyncResult asyn) } catch { - //Other errors are discarded to keep proxy running + // Other errors are discarded to keep proxy running } if (tcpClient != null) diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index 0865cd1eb..2fa7a9e2c 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -51,8 +51,8 @@ private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientCon try { - //Loop through each subsequest request on this particular client connection - //(assuming HTTP connection is kept alive by client) + // Loop through each subsequest request on this particular client connection + // (assuming HTTP connection is kept alive by client) while (true) { // read the request line @@ -76,7 +76,7 @@ private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientCon Request.ParseRequestLine(httpCmd, out string httpMethod, out string httpUrl, out var version); - //Read the request headers in to unique and non-unique header collections + // Read the request headers in to unique and non-unique header collections await HeaderParser.ReadHeaders(clientStream, args.WebSession.Request.Headers, cancellationToken); @@ -124,12 +124,12 @@ await HeaderParser.ReadHeaders(clientStream, args.WebSession.Request.Headers, if (!args.IsTransparent) { - //proxy authorization check + // proxy authorization check if (httpsConnectHostname == null && await CheckAuthorization(args) == false) { await InvokeBeforeResponse(args); - //send the response + // send the response await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, cancellationToken: cancellationToken); return; @@ -139,9 +139,9 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, request.Host = request.RequestUri.Authority; } - //if win auth is enabled - //we need a cache of request body - //so that we can send it after authentication in WinAuthHandler.cs + // if win auth is enabled + // we need a cache of request body + // so that we can send it after authentication in WinAuthHandler.cs if (isWindowsAuthenticationEnabledAndSupported && request.HasBody) { await args.GetRequestBody(cancellationToken); @@ -149,14 +149,14 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, request.OriginalHasBody = request.HasBody; - //If user requested interception do it + // If user requested interception do it await InvokeBeforeRequest(args); var response = args.WebSession.Response; if (request.CancelRequest) { - //syphon out the request body from client before setting the new body + // syphon out the request body from client before setting the new body await args.SyphonOutBodyAsync(true, cancellationToken); await HandleHttpSessionResponse(args); @@ -169,7 +169,7 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, continue; } - //create a new connection if hostname/upstream end point changes + // create a new connection if hostname/upstream end point changes if (serverConnection != null && (!serverConnection.HostName.Equals(request.RequestUri.Host, StringComparison.OrdinalIgnoreCase) @@ -185,10 +185,10 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, serverConnection = await GetServerConnection(args, false, cancellationToken); } - //if upgrading to websocket then relay the requet without reading the contents + // if upgrading to websocket then relay the requet without reading the contents if (request.UpgradeToWebSocket) { - //prepare the prefix content + // prepare the prefix content await serverConnection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken); await serverConnection.StreamWriter.WriteHeadersAsync(request.Headers, cancellationToken: cancellationToken); @@ -210,7 +210,7 @@ await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken); } - //If user requested call back then do it + // If user requested call back then do it if (!args.WebSession.Response.Locked) { await InvokeBeforeResponse(args); @@ -224,7 +224,7 @@ await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferSize, return; } - //construct the web request that we are going to issue on behalf of the client. + // construct the web request that we are going to issue on behalf of the client. await HandleHttpSessionRequestInternal(serverConnection, args); if (args.WebSession.ServerConnection == null) @@ -232,7 +232,7 @@ await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferSize, return; } - //if connection is closing exit + // if connection is closing exit if (!response.KeepAlive) { return; @@ -282,8 +282,8 @@ private async Task HandleHttpSessionRequestInternal(TcpServerConnection serverCo var body = request.CompressBodyAndUpdateContentLength(); - //if expect continue is enabled then send the headers first - //and see if server would return 100 conitinue + // if expect continue is enabled then send the headers first + // and see if server would return 100 conitinue if (request.ExpectContinue) { args.WebSession.SetConnection(serverConnection); @@ -291,7 +291,7 @@ await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent cancellationToken); } - //If 100 continue was the response inform that to the client + // If 100 continue was the response inform that to the client if (Enable100ContinueBehaviour) { var clientStreamWriter = args.ProxyClient.ClientStreamWriter; @@ -310,7 +310,7 @@ await clientStreamWriter.WriteResponseStatusAsync(args.WebSession.Response.HttpV } } - //If expect continue is not enabled then set the connectio and send request headers + // If expect continue is not enabled then set the connectio and send request headers if (!request.ExpectContinue) { args.WebSession.SetConnection(serverConnection); @@ -318,7 +318,7 @@ await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent cancellationToken); } - //check if content-length is > 0 + // check if content-length is > 0 if (request.ContentLength > 0) { if (request.IsBodyRead) @@ -339,7 +339,7 @@ await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent } } - //If not expectation failed response was returned by server then parse response + // If not expectation failed response was returned by server then parse response if (!request.ExpectationFailed) { await HandleHttpSessionResponse(args); diff --git a/Titanium.Web.Proxy/ResponseHandler.cs b/Titanium.Web.Proxy/ResponseHandler.cs index 03f34fb30..b445f9926 100644 --- a/Titanium.Web.Proxy/ResponseHandler.cs +++ b/Titanium.Web.Proxy/ResponseHandler.cs @@ -23,13 +23,13 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) try { var cancellationToken = args.CancellationTokenSource.Token; - //read response & headers from server + // read response & headers from server await args.WebSession.ReceiveResponse(cancellationToken); var response = args.WebSession.Response; args.ReRequest = false; - //check for windows authentication + // check for windows authentication if (isWindowsAuthenticationEnabledAndSupported) { if (response.StatusCode == (int)HttpStatusCode.Unauthorized) @@ -44,7 +44,7 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) response.OriginalHasBody = response.HasBody; - //if user requested call back then do it + // if user requested call back then do it if (!response.Locked) { await InvokeBeforeResponse(args); @@ -61,7 +61,7 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) if (!response.TerminateResponse) { - //syphon out the response body from server before setting the new body + // syphon out the response body from server before setting the new body await args.SyphonOutBodyAsync(false, cancellationToken); } else @@ -73,11 +73,11 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) return; } - //if user requested to send request again - //likely after making modifications from User Response Handler + // if user requested to send request again + // likely after making modifications from User Response Handler if (args.ReRequest) { - //clear current response + // clear current response await args.ClearResponse(cancellationToken); await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args); return; @@ -85,7 +85,7 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) response.Locked = true; - //Write back to client 100-conitinue response if that's what server returned + // Write back to client 100-conitinue response if that's what server returned if (response.Is100Continue) { await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, @@ -110,12 +110,12 @@ await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, } else { - //Write back response status to client + // Write back response status to client await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription, cancellationToken); await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken: cancellationToken); - //Write body if exists + // Write body if exists if (response.HasBody) { await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None, diff --git a/Titanium.Web.Proxy/TransparentClientHandler.cs b/Titanium.Web.Proxy/TransparentClientHandler.cs index e29530c46..80e0d9e4a 100644 --- a/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -69,10 +69,10 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConn string certName = HttpHelper.GetWildCardDomainName(httpsHostName); var certificate = await CertificateManager.CreateCertificateAsync(certName); - //Successfully managed to authenticate the client using the fake certificate + // Successfully managed to authenticate the client using the fake certificate await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false); - //HTTPS server created - we can now decrypt the client's traffic + // HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); @@ -86,7 +86,7 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConn } else { - //create new connection + // create new connection var connection = new TcpClient(UpStreamEndPoint); await connection.ConnectAsync(httpsHostName, endPoint.Port); connection.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; @@ -123,8 +123,8 @@ await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, } } - //HTTPS server created - we can now decrypt the client's traffic - //Now create the request + // HTTPS server created - we can now decrypt the client's traffic + // Now create the request await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource, isHttps ? httpsHostName : null, null); } diff --git a/Titanium.Web.Proxy/WinAuthHandler.cs b/Titanium.Web.Proxy/WinAuthHandler.cs index 7155c628c..1e9e9f4ff 100644 --- a/Titanium.Web.Proxy/WinAuthHandler.cs +++ b/Titanium.Web.Proxy/WinAuthHandler.cs @@ -19,7 +19,8 @@ public partial class ProxyServer private static readonly HashSet authHeaderNames = new HashSet(StringComparer.OrdinalIgnoreCase) { "WWW-Authenticate", - //IIS 6.0 messed up names below + + // IIS 6.0 messed up names below "WWWAuthenticate", "NTLMAuthorization", "NegotiateAuthorization", @@ -51,7 +52,7 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) var response = args.WebSession.Response; - //check in non-unique headers first + // check in non-unique headers first var header = response.Headers.NonUniqueHeaders.FirstOrDefault(x => authHeaderNames.Contains(x.Key)); if (!header.Equals(new KeyValuePair>())) @@ -66,12 +67,12 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) x => authSchemes.Any(y => x.Value.StartsWith(y, StringComparison.OrdinalIgnoreCase))); } - //check in unique headers + // check in unique headers if (authHeader == null) { headerName = null; - //check in non-unique headers first + // check in non-unique headers first var uHeader = response.Headers.Headers.FirstOrDefault(x => authHeaderNames.Contains(x.Key)); if (!uHeader.Equals(new KeyValuePair())) @@ -104,26 +105,26 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) var request = args.WebSession.Request; - //clear any existing headers to avoid confusing bad servers + // clear any existing headers to avoid confusing bad servers request.Headers.RemoveHeader(KnownHeaders.Authorization); - //initial value will match exactly any of the schemes + // initial value will match exactly any of the schemes if (scheme != null) { string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host, scheme, args.Id); string auth = string.Concat(scheme, clientToken); - //replace existing authorization header if any + // replace existing authorization header if any request.Headers.SetOrAddHeaderValue(KnownHeaders.Authorization, auth); - //don't need to send body for Authorization request + // don't need to send body for Authorization request if (request.HasBody) { request.ContentLength = 0; } } - //challenge value will start with any of the scheme selected + // challenge value will start with any of the scheme selected else { scheme = authSchemes.First(x => @@ -135,19 +136,19 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) string auth = string.Concat(scheme, clientToken); - //there will be an existing header from initial client request + // there will be an existing header from initial client request request.Headers.SetOrAddHeaderValue(KnownHeaders.Authorization, auth); - //send body for final auth request + // send body for final auth request if (request.OriginalHasBody) { request.ContentLength = request.Body.Length; } } - //Need to revisit this. - //Should we cache all Set-Cokiee headers from server during auth process - //and send it to client after auth? + // Need to revisit this. + // Should we cache all Set-Cokiee headers from server during auth process + // and send it to client after auth? // Let ResponseHandler send the updated request args.ReRequest = true; From 3bf4649c4ae19ae0d927fdc3a1aaa75978b555cd Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 1 May 2018 11:43:33 +0200 Subject: [PATCH 09/23] stylecop fixes --- .../EventArguments/SessionEventArgsBase.cs | 2 +- .../EventArguments/TunnelConnectEventArgs.cs | 1 + .../Exceptions/ProxyAuthorizationException.cs | 2 +- .../Exceptions/ProxyConnectException.cs | 2 +- .../Exceptions/ProxyException.cs | 6 +- .../Exceptions/ProxyHttpException.cs | 2 +- Titanium.Web.Proxy/ExplicitClientHandler.cs | 4 +- .../Extensions/SslExtensions.cs | 2 + Titanium.Web.Proxy/Helpers/HttpHelper.cs | 2 +- Titanium.Web.Proxy/Helpers/Network.cs | 1 + Titanium.Web.Proxy/Helpers/SystemProxy.cs | 3 +- Titanium.Web.Proxy/Http/HttpWebClient.cs | 3 +- Titanium.Web.Proxy/Http/Request.cs | 2 +- .../Http/RequestResponseBase.cs | 8 +- Titanium.Web.Proxy/Http/Response.cs | 2 +- .../Http/Responses/GenericResponse.cs | 6 +- .../Http/Responses/RedirectResponse.cs | 2 +- .../Network/CertificateManager.cs | 20 +-- .../Network/WinAuth/Security/Message.cs | 2 - .../WinAuth/Security/WinAuthEndPoint.cs | 17 +- .../Network/WinAuth/WinAuthHandler.cs | 3 +- Titanium.Web.Proxy/ProxyServer.cs | 9 +- Titanium.Web.Proxy/RequestHandler.cs | 11 +- Titanium.Web.Proxy/ResponseHandler.cs | 3 +- Titanium.Web.Proxy/Settings.StyleCop | 159 ++++++++++++++++++ .../TransparentClientHandler.cs | 4 +- Titanium.Web.Proxy/WinAuthHandler.cs | 3 +- 27 files changed, 218 insertions(+), 63 deletions(-) create mode 100644 Titanium.Web.Proxy/Settings.StyleCop diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index 1729ca16a..cfc7b8b59 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -27,7 +27,7 @@ public abstract class SessionEventArgsBase : EventArgs, IDisposable protected readonly ExceptionHandler ExceptionFunc; /// - /// Constructor to initialize the proxy + /// Initializes a new instance of the class. /// internal SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc) diff --git a/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs b/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs index e964d86c9..372a2da87 100644 --- a/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs +++ b/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs @@ -37,6 +37,7 @@ public bool IsHttpsConnect { get => isHttpsConnect ?? throw new Exception("The value of this property is known in the BeforeTunnectConnectResponse event"); + internal set => isHttpsConnect = value; } } diff --git a/Titanium.Web.Proxy/Exceptions/ProxyAuthorizationException.cs b/Titanium.Web.Proxy/Exceptions/ProxyAuthorizationException.cs index 51cd95c57..1860711ff 100644 --- a/Titanium.Web.Proxy/Exceptions/ProxyAuthorizationException.cs +++ b/Titanium.Web.Proxy/Exceptions/ProxyAuthorizationException.cs @@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Exceptions public class ProxyAuthorizationException : ProxyException { /// - /// Instantiate new instance. + /// Initializes a new instance of the class. /// /// Exception message. /// The instance containing the event data. diff --git a/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs b/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs index bc6718df2..a06da89fb 100644 --- a/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs +++ b/Titanium.Web.Proxy/Exceptions/ProxyConnectException.cs @@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.Exceptions public class ProxyConnectException : ProxyException { /// - /// Instantiate new instance + /// Initializes a new instance of the class. /// /// Message for this exception /// Associated inner exception diff --git a/Titanium.Web.Proxy/Exceptions/ProxyException.cs b/Titanium.Web.Proxy/Exceptions/ProxyException.cs index 2df226dcf..424edf8bc 100644 --- a/Titanium.Web.Proxy/Exceptions/ProxyException.cs +++ b/Titanium.Web.Proxy/Exceptions/ProxyException.cs @@ -8,7 +8,8 @@ namespace Titanium.Web.Proxy.Exceptions public abstract class ProxyException : Exception { /// - /// Instantiate a new instance of this exception - must be invoked by derived classes' constructors + /// Initializes a new instance of the class. + /// - must be invoked by derived classes' constructors /// /// Exception message protected ProxyException(string message) : base(message) @@ -16,7 +17,8 @@ protected ProxyException(string message) : base(message) } /// - /// Instantiate this exception - must be invoked by derived classes' constructors + /// Initializes a new instance of the class. + /// - must be invoked by derived classes' constructors /// /// Excception message /// Inner exception associated diff --git a/Titanium.Web.Proxy/Exceptions/ProxyHttpException.cs b/Titanium.Web.Proxy/Exceptions/ProxyHttpException.cs index fb0382a42..8aeccaadd 100644 --- a/Titanium.Web.Proxy/Exceptions/ProxyHttpException.cs +++ b/Titanium.Web.Proxy/Exceptions/ProxyHttpException.cs @@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.Exceptions public class ProxyHttpException : ProxyException { /// - /// Instantiate new instance + /// Initializes a new instance of the class. /// /// Message for this exception /// Associated inner exception diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index 2dd97eefe..c42668e7b 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy { - partial class ProxyServer + public partial class ProxyServer { /// /// This is called when client is aware of proxy @@ -278,7 +278,7 @@ await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, // Now create the request await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, - cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); + cancellationTokenSource, connectHostname, connectArgs?.WebSession.ConnectRequest); } catch (ProxyException e) { diff --git a/Titanium.Web.Proxy/Extensions/SslExtensions.cs b/Titanium.Web.Proxy/Extensions/SslExtensions.cs index f17e4f46a..f9889cc52 100644 --- a/Titanium.Web.Proxy/Extensions/SslExtensions.cs +++ b/Titanium.Web.Proxy/Extensions/SslExtensions.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Net.Security; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; @@ -81,6 +82,7 @@ internal enum SslApplicationProtocol Http2 } + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Reviewed.")] internal class SslClientAuthenticationOptions { internal bool AllowRenegotiation { get; set; } diff --git a/Titanium.Web.Proxy/Helpers/HttpHelper.cs b/Titanium.Web.Proxy/Helpers/HttpHelper.cs index e24717198..f4b6f5d5c 100644 --- a/Titanium.Web.Proxy/Helpers/HttpHelper.cs +++ b/Titanium.Web.Proxy/Helpers/HttpHelper.cs @@ -35,7 +35,7 @@ internal static Encoding GetEncodingFromContentType(string contentType) if (split.Length == 2 && split[0].Trim().EqualsIgnoreCase(KnownHeaders.ContentTypeCharset)) { string value = split[1]; - if (value.Equals("x-user-defined", StringComparison.OrdinalIgnoreCase)) + if (value.EqualsIgnoreCase("x-user-defined")) { continue; } diff --git a/Titanium.Web.Proxy/Helpers/Network.cs b/Titanium.Web.Proxy/Helpers/Network.cs index 1e315ee11..7b4ca2feb 100644 --- a/Titanium.Web.Proxy/Helpers/Network.cs +++ b/Titanium.Web.Proxy/Helpers/Network.cs @@ -21,6 +21,7 @@ internal static bool IsLocalIpAddress(IPAddress address) // get local IP addresses var localIPs = Dns.GetHostAddresses(Dns.GetHostName()); + // test if any host IP equals to any local IP or to localhost return localIPs.Contains(address); } diff --git a/Titanium.Web.Proxy/Helpers/SystemProxy.cs b/Titanium.Web.Proxy/Helpers/SystemProxy.cs index de1253489..8ca559c18 100644 --- a/Titanium.Web.Proxy/Helpers/SystemProxy.cs +++ b/Titanium.Web.Proxy/Helpers/SystemProxy.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.Win32; using Titanium.Web.Proxy.Models; @@ -6,7 +7,6 @@ // Helper classes for setting system proxy settings namespace Titanium.Web.Proxy.Helpers { - internal class HttpSystemProxyValue { internal string HostName { get; set; } @@ -37,6 +37,7 @@ public override string ToString() /// /// Manage system proxy settings /// + [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Reviewed.")] internal class SystemProxyManager { private const string regKeyInternetSettings = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; diff --git a/Titanium.Web.Proxy/Http/HttpWebClient.cs b/Titanium.Web.Proxy/Http/HttpWebClient.cs index cd0409671..f461bdd11 100644 --- a/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -93,8 +93,7 @@ internal async Task SendRequest(bool enable100ContinueBehaviour, bool isTranspar await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery, Request.HttpVersion), cancellationToken); - - + // Send Authentication to Upstream proxy if needed if (!isTransparent && upstreamProxy != null && ServerConnection.IsHttps == false diff --git a/Titanium.Web.Proxy/Http/Request.cs b/Titanium.Web.Proxy/Http/Request.cs index d67228626..41ae547eb 100644 --- a/Titanium.Web.Proxy/Http/Request.cs +++ b/Titanium.Web.Proxy/Http/Request.cs @@ -212,7 +212,7 @@ internal static void ParseRequestLine(string httpCmd, out string httpMethod, out { string httpVersion = httpCmdSplit[2].Trim(); - if (string.Equals(httpVersion, "HTTP/1.0", StringComparison.OrdinalIgnoreCase)) + if (httpVersion.EqualsIgnoreCase("HTTP/1.0")) { version = HttpHeader.Version10; } diff --git a/Titanium.Web.Proxy/Http/RequestResponseBase.cs b/Titanium.Web.Proxy/Http/RequestResponseBase.cs index 6fe6878cf..209ba9401 100644 --- a/Titanium.Web.Proxy/Http/RequestResponseBase.cs +++ b/Titanium.Web.Proxy/Http/RequestResponseBase.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Text; using Titanium.Web.Proxy.Compression; @@ -14,7 +15,7 @@ public abstract class RequestResponseBase /// /// Cached body content as byte array. /// - protected byte[] BodyInternal; + protected byte[] BodyInternal { get; private set; } /// /// Cached body as string. @@ -24,7 +25,7 @@ public abstract class RequestResponseBase /// /// Store weather the original request/response has body or not, since the user may change the parameters /// - internal bool OriginalHasBody; + internal bool OriginalHasBody { get; set; } /// /// Keeps the body data after the session is finished. @@ -62,6 +63,7 @@ public long ContentLength return -1; } + set { if (value >= 0) @@ -105,6 +107,7 @@ public bool IsChunked string headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.TransferEncoding); return headerValue != null && headerValue.ContainsIgnoreCase(KnownHeaders.TransferEncodingChunked); } + set { if (value) @@ -135,6 +138,7 @@ public byte[] Body EnsureBodyAvailable(); return BodyInternal; } + internal set { BodyInternal = value; diff --git a/Titanium.Web.Proxy/Http/Response.cs b/Titanium.Web.Proxy/Http/Response.cs index 650292cda..39d9a90c5 100644 --- a/Titanium.Web.Proxy/Http/Response.cs +++ b/Titanium.Web.Proxy/Http/Response.cs @@ -155,7 +155,7 @@ internal static void ParseResponseLine(string httpStatus, out Version version, o string httpVersion = httpResult[0]; version = HttpHeader.Version11; - if (string.Equals(httpVersion, "HTTP/1.0", StringComparison.OrdinalIgnoreCase)) + if (httpVersion.EqualsIgnoreCase("HTTP/1.0")) { version = HttpHeader.Version10; } diff --git a/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs b/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs index 0646d83d9..273b4028c 100644 --- a/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs +++ b/Titanium.Web.Proxy/Http/Responses/GenericResponse.cs @@ -3,9 +3,9 @@ namespace Titanium.Web.Proxy.Http.Responses { - ///  - /// Anything other than a 200 or 302 response - ///  + /// + /// Anything other than a 200 or 302 response + /// public class GenericResponse : Response { /// diff --git a/Titanium.Web.Proxy/Http/Responses/RedirectResponse.cs b/Titanium.Web.Proxy/Http/Responses/RedirectResponse.cs index be9a44723..4d602b0bf 100644 --- a/Titanium.Web.Proxy/Http/Responses/RedirectResponse.cs +++ b/Titanium.Web.Proxy/Http/Responses/RedirectResponse.cs @@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Http.Responses public sealed class RedirectResponse : Response { /// - /// Constructor. + /// Initializes a new instance of the class. /// public RedirectResponse() { diff --git a/Titanium.Web.Proxy/Network/CertificateManager.cs b/Titanium.Web.Proxy/Network/CertificateManager.cs index 12607b045..e5612907b 100644 --- a/Titanium.Web.Proxy/Network/CertificateManager.cs +++ b/Titanium.Web.Proxy/Network/CertificateManager.cs @@ -57,9 +57,9 @@ public sealed class CertificateManager : IDisposable private X509Certificate2 rootCertificate; private string rootCertificateName; - - + /// + /// Initializes a new instance of the class. /// /// /// @@ -241,8 +241,7 @@ public X509Certificate2 RootCertificate public void Dispose() { } - - + private string GetRootCertificateDirectory() { string assemblyLocation = Assembly.GetExecutingAssembly().Location; @@ -254,7 +253,7 @@ private string GetRootCertificateDirectory() } string path = Path.GetDirectoryName(assemblyLocation); - if (null == path) + if (path == null) { throw new NullReferenceException(); } @@ -322,7 +321,6 @@ private X509Certificate2Collection FindCertificates(StoreName storeName, StoreLo /// /// /// - /// private void InstallCertificate(StoreName storeName, StoreLocation storeLocation) { if (RootCertificate == null) @@ -359,7 +357,6 @@ private void InstallCertificate(StoreName storeName, StoreLocation storeLocation /// /// /// - /// private void UninstallCertificate(StoreName storeName, StoreLocation storeLocation, X509Certificate2 certificate) { @@ -447,9 +444,9 @@ internal X509Certificate2 CreateCertificate(string certificateName, bool isRootC { certificate = new X509Certificate2(certificatePath, string.Empty, StorageFlag); } - // if load failed create again catch { + // if load failed create again certificate = MakeCertificate(certificateName, false); } } @@ -532,8 +529,7 @@ internal async void ClearIdleCertificates() await Task.Delay(1000 * 60); } } - - + /// /// Stops the certificate cache clear process /// @@ -779,8 +775,7 @@ public void EnsureRootCertificate(bool userTrustRootCertificate, EnsureRootCertificate(); } - - + /// /// Determines whether the root certificate is trusted. /// @@ -866,6 +861,7 @@ public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false) ErrorDialog = false, WindowStyle = ProcessWindowStyle.Hidden }, + // currentUser\Personal & currentMachine\Personal new ProcessStartInfo { diff --git a/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs b/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs index 125a0b29b..1a1abc343 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs @@ -65,8 +65,6 @@ internal Message(byte[] message) // methods private void Decode(byte[] message) { - //base.Decode (message); - if (message == null) { throw new ArgumentNullException(nameof(message)); diff --git a/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs b/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs index 20fa4e261..9e0847383 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs @@ -18,8 +18,7 @@ internal class WinAuthEndPoint /// Keep track of auth states for reuse in final challenge response /// private static readonly IDictionary authStates = new ConcurrentDictionary(); - - + /// /// Acquire the intial client token to send /// @@ -68,8 +67,7 @@ internal static byte[] AcquireInitialSecurityToken(string hostname, string authS out clientToken, out NewContextAttributes, out NewLifeTime); - - + if (result != IntermediateResult) { return null; @@ -122,8 +120,7 @@ internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverC out clientToken, out NewContextAttributes, out NewLifeTime); - - + if (result != SuccessfulResult) { return null; @@ -173,18 +170,16 @@ internal static bool ValidateWinAuthState(Guid requestId, State.WinAuthState exp if (expectedAuthState == State.WinAuthState.UNAUTHORIZED) { - return stateExists == false || + return !stateExists || state.AuthState == State.WinAuthState.UNAUTHORIZED || - state.AuthState == - State.WinAuthState.AUTHORIZED; // Server may require re-authentication on an open connection + state.AuthState == State.WinAuthState.AUTHORIZED; // Server may require re-authentication on an open connection } if (expectedAuthState == State.WinAuthState.INITIAL_TOKEN) { return stateExists && (state.AuthState == State.WinAuthState.INITIAL_TOKEN || - state.AuthState == State.WinAuthState.AUTHORIZED - ); // Server may require re-authentication on an open connection + state.AuthState == State.WinAuthState.AUTHORIZED); // Server may require re-authentication on an open connection } throw new Exception("Unsupported validation of WinAuthState"); diff --git a/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs b/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs index a445f5d45..c978299a4 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs @@ -23,8 +23,7 @@ internal static string GetInitialAuthToken(string serverHostname, string authSch var tokenBytes = WinAuthEndPoint.AcquireInitialSecurityToken(serverHostname, authScheme, requestId); return string.Concat(" ", Convert.ToBase64String(tokenBytes)); } - - + /// /// Get the final token given the server challenge token /// diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index e581706f3..1811867a2 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using StreamExtended.Network; using Titanium.Web.Proxy.EventArguments; +using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers.WinHttp; using Titanium.Web.Proxy.Models; @@ -25,7 +26,7 @@ namespace Titanium.Web.Proxy public partial class ProxyServer : IDisposable { /// - /// HTTP & HTTPS scheme shorthands. + /// HTTP & HTTPS scheme shorthands. /// internal static readonly string UriSchemeHttp = Uri.UriSchemeHttp; @@ -170,8 +171,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, /// Realm used during Proxy Basic Authentication. /// public string ProxyRealm { get; set; } = "TitaniumProxy"; - - + /// /// List of supported Ssl versions. /// @@ -181,7 +181,6 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, #endif SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; - /// /// Manages certificates used by this proxy. /// @@ -483,7 +482,7 @@ public void Start() foreach (var proxy in proxyInfo.Proxies.Values) { if ((proxy.HostName == "127.0.0.1" - || proxy.HostName.Equals("localhost", StringComparison.OrdinalIgnoreCase)) + || proxy.HostName.EqualsIgnoreCase("localhost")) && ProxyEndPoints.Any(x => x.Port == proxy.Port)) { protocolToRemove |= proxy.ProtocolType; diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index 2fa7a9e2c..bfd225db3 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy /// /// Handle the request /// - partial class ProxyServer + public partial class ProxyServer { private static readonly Regex uriSchemeRegex = new Regex("^[a-z]*://", RegexOptions.IgnoreCase | RegexOptions.Compiled); @@ -40,8 +40,6 @@ partial class ProxyServer /// explicit endpoint. /// /// The Connect request if this is a HTTPS request from explicit endpoint. - /// Is this a request from transparent endpoint? - /// private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest) @@ -171,10 +169,9 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, // create a new connection if hostname/upstream end point changes if (serverConnection != null - && (!serverConnection.HostName.Equals(request.RequestUri.Host, - StringComparison.OrdinalIgnoreCase) - || args.WebSession.UpStreamEndPoint != null - && !args.WebSession.UpStreamEndPoint.Equals(serverConnection.UpStreamEndPoint))) + && (!serverConnection.HostName.EqualsIgnoreCase(request.RequestUri.Host) + || args.WebSession.UpStreamEndPoint?.Equals(serverConnection.UpStreamEndPoint) == + false)) { serverConnection.Dispose(); serverConnection = null; diff --git a/Titanium.Web.Proxy/ResponseHandler.cs b/Titanium.Web.Proxy/ResponseHandler.cs index b445f9926..2ab17ce93 100644 --- a/Titanium.Web.Proxy/ResponseHandler.cs +++ b/Titanium.Web.Proxy/ResponseHandler.cs @@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy /// /// Handle the response from server. /// - partial class ProxyServer + public partial class ProxyServer { /// /// Called asynchronously when a request was successfully and we received the response. @@ -23,6 +23,7 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) try { var cancellationToken = args.CancellationTokenSource.Token; + // read response & headers from server await args.WebSession.ReceiveResponse(cancellationToken); diff --git a/Titanium.Web.Proxy/Settings.StyleCop b/Titanium.Web.Proxy/Settings.StyleCop new file mode 100644 index 000000000..eff034d87 --- /dev/null +++ b/Titanium.Web.Proxy/Settings.StyleCop @@ -0,0 +1,159 @@ + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/Titanium.Web.Proxy/TransparentClientHandler.cs b/Titanium.Web.Proxy/TransparentClientHandler.cs index 80e0d9e4a..5938859c5 100644 --- a/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy { - partial class ProxyServer + public partial class ProxyServer { /// /// This is called when this proxy acts as a reverse proxy (like a real http server). @@ -115,7 +115,7 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConn } } - //var serverHelloInfo = await SslTools.PeekServerHello(serverStream); + ////var serverHelloInfo = await SslTools.PeekServerHello(serverStream); await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, null, null, cancellationTokenSource, ExceptionFunc); diff --git a/Titanium.Web.Proxy/WinAuthHandler.cs b/Titanium.Web.Proxy/WinAuthHandler.cs index 1e9e9f4ff..0559c66a4 100644 --- a/Titanium.Web.Proxy/WinAuthHandler.cs +++ b/Titanium.Web.Proxy/WinAuthHandler.cs @@ -124,9 +124,10 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) request.ContentLength = 0; } } - // challenge value will start with any of the scheme selected else { + // challenge value will start with any of the scheme selected + scheme = authSchemes.First(x => authHeader.Value.StartsWith(x, StringComparison.OrdinalIgnoreCase) && authHeader.Value.Length > x.Length + 1); From b4e71fcb5636ac24960380435122f6a07034e5da Mon Sep 17 00:00:00 2001 From: buildbot121 Date: Tue, 1 May 2018 02:45:30 -0700 Subject: [PATCH 10/23] API documentation update by build server --- ...m.Web.Proxy.Exceptions.ProxyException.html | 10 ++++++-- ...um.Web.Proxy.Http.RequestResponseBase.html | 23 +++++++++---------- ...Proxy.Http.Responses.RedirectResponse.html | 2 +- docs/index.json | 6 ++--- docs/xrefmap.yml | 9 +++++++- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html index af225e96e..08222fbca 100644 --- a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html +++ b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html @@ -169,7 +169,10 @@

    Constructors

    ProxyException(String)

    -

    Instantiate a new instance of this exception - must be invoked by derived classes' constructors

    +

    Initializes a new instance of the ProxyException class.

    +
      +
    • must be invoked by derived classes' constructors
    • +
    Declaration
    @@ -198,7 +201,10 @@
    Parameters

    ProxyException(String, Exception)

    -

    Instantiate this exception - must be invoked by derived classes' constructors

    +

    Initializes a new instance of the ProxyException class.

    +
      +
    • must be invoked by derived classes' constructors
    • +
    Declaration
    diff --git a/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html b/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html index 37b2e275c..0075c6a26 100644 --- a/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html +++ b/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html @@ -119,19 +119,21 @@
    Syntax
    public abstract class RequestResponseBase
    -

    Fields +

    Properties

    -

    BodyInternal

    -

    Cached body content as byte array.

    + +

    Body

    +

    Body as byte array

    Declaration
    -
    protected byte[] BodyInternal
    +
    [Browsable(false)]
    +public byte[] Body { get; }
    -
    Field Value
    +
    Property Value
    @@ -146,19 +148,16 @@
    Field Value
    -

    Properties -

    - -

    Body

    -

    Body as byte array

    + +

    BodyInternal

    +

    Cached body content as byte array.

    Declaration
    -
    [Browsable(false)]
    -public byte[] Body { get; }
    +
    protected byte[] BodyInternal { get; }
    Property Value
    diff --git a/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html b/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html index 15cb7d105..500062082 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html +++ b/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html @@ -186,7 +186,7 @@

    Constructors

    RedirectResponse()

    -

    Constructor.

    +

    Initializes a new instance of the RedirectResponse class.

    Declaration
    diff --git a/docs/index.json b/docs/index.json index 1383ac9b1..da5642ec3 100644 --- a/docs/index.json +++ b/docs/index.json @@ -67,7 +67,7 @@ "api/Titanium.Web.Proxy.Exceptions.ProxyException.html": { "href": "api/Titanium.Web.Proxy.Exceptions.ProxyException.html", "title": "Class ProxyException | Titanium Web Proxy", - "keywords": "Class ProxyException Base class exception associated with this proxy server. Inheritance Object Exception ProxyException BodyNotFoundException ProxyAuthorizationException ProxyHttpException Implements ISerializable _Exception Inherited Members Exception.GetBaseException() Exception.ToString() Exception.GetObjectData(SerializationInfo, StreamingContext) Exception.GetType() Exception.Message Exception.Data Exception.InnerException Exception.TargetSite Exception.StackTrace Exception.HelpLink Exception.Source Exception.HResult Exception.SerializeObjectState Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Exceptions Assembly : Titanium.Web.Proxy.dll Syntax public abstract class ProxyException : Exception, ISerializable, _Exception Constructors ProxyException(String) Instantiate a new instance of this exception - must be invoked by derived classes' constructors Declaration protected ProxyException(string message) Parameters Type Name Description String message Exception message ProxyException(String, Exception) Instantiate this exception - must be invoked by derived classes' constructors Declaration protected ProxyException(string message, Exception innerException) Parameters Type Name Description String message Excception message Exception innerException Inner exception associated Implements System.Runtime.Serialization.ISerializable System.Runtime.InteropServices._Exception" + "keywords": "Class ProxyException Base class exception associated with this proxy server. Inheritance Object Exception ProxyException BodyNotFoundException ProxyAuthorizationException ProxyHttpException Implements ISerializable _Exception Inherited Members Exception.GetBaseException() Exception.ToString() Exception.GetObjectData(SerializationInfo, StreamingContext) Exception.GetType() Exception.Message Exception.Data Exception.InnerException Exception.TargetSite Exception.StackTrace Exception.HelpLink Exception.Source Exception.HResult Exception.SerializeObjectState Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Exceptions Assembly : Titanium.Web.Proxy.dll Syntax public abstract class ProxyException : Exception, ISerializable, _Exception Constructors ProxyException(String) Initializes a new instance of the ProxyException class. must be invoked by derived classes' constructors Declaration protected ProxyException(string message) Parameters Type Name Description String message Exception message ProxyException(String, Exception) Initializes a new instance of the ProxyException class. must be invoked by derived classes' constructors Declaration protected ProxyException(string message, Exception innerException) Parameters Type Name Description String message Excception message Exception innerException Inner exception associated Implements System.Runtime.Serialization.ISerializable System.Runtime.InteropServices._Exception" }, "api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html": { "href": "api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html", @@ -117,7 +117,7 @@ "api/Titanium.Web.Proxy.Http.RequestResponseBase.html": { "href": "api/Titanium.Web.Proxy.Http.RequestResponseBase.html", "title": "Class RequestResponseBase | Titanium Web Proxy", - "keywords": "Class RequestResponseBase Inheritance Object RequestResponseBase Request Response Inherited Members Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Http Assembly : Titanium.Web.Proxy.dll Syntax public abstract class RequestResponseBase Fields BodyInternal Cached body content as byte array. Declaration protected byte[] BodyInternal Field Value Type Description System.Byte [] Properties Body Body as byte array Declaration [Browsable(false)] public byte[] Body { get; } Property Value Type Description System.Byte [] BodyString Body as string. Use the encoding specified to decode the byte[] data to string Declaration [Browsable(false)] public string BodyString { get; } Property Value Type Description String ContentEncoding Content encoding for this request/response. Declaration public string ContentEncoding { get; } Property Value Type Description String ContentLength Length of the body. Declaration public long ContentLength { get; set; } Property Value Type Description Int64 ContentType Content-type of the request/response. Declaration public string ContentType { get; set; } Property Value Type Description String Encoding Encoding for this request/response. Declaration public Encoding Encoding { get; } Property Value Type Description Encoding HasBody Has the request/response body? Declaration public abstract bool HasBody { get; } Property Value Type Description Boolean Headers Collection of all headers. Declaration public HeaderCollection Headers { get; } Property Value Type Description HeaderCollection HeaderText The header text. Declaration public abstract string HeaderText { get; } Property Value Type Description String HttpVersion Http Version. Declaration public Version HttpVersion { get; set; } Property Value Type Description Version IsBodyRead Was the body read by user? Declaration public bool IsBodyRead { get; } Property Value Type Description Boolean IsChunked Is body send as chunked bytes. Declaration public bool IsChunked { get; set; } Property Value Type Description Boolean KeepBody Keeps the body data after the session is finished. Declaration public bool KeepBody { get; set; } Property Value Type Description Boolean Methods ToString() Declaration public override string ToString() Returns Type Description String Overrides Object.ToString()" + "keywords": "Class RequestResponseBase Inheritance Object RequestResponseBase Request Response Inherited Members Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Http Assembly : Titanium.Web.Proxy.dll Syntax public abstract class RequestResponseBase Properties Body Body as byte array Declaration [Browsable(false)] public byte[] Body { get; } Property Value Type Description System.Byte [] BodyInternal Cached body content as byte array. Declaration protected byte[] BodyInternal { get; } Property Value Type Description System.Byte [] BodyString Body as string. Use the encoding specified to decode the byte[] data to string Declaration [Browsable(false)] public string BodyString { get; } Property Value Type Description String ContentEncoding Content encoding for this request/response. Declaration public string ContentEncoding { get; } Property Value Type Description String ContentLength Length of the body. Declaration public long ContentLength { get; set; } Property Value Type Description Int64 ContentType Content-type of the request/response. Declaration public string ContentType { get; set; } Property Value Type Description String Encoding Encoding for this request/response. Declaration public Encoding Encoding { get; } Property Value Type Description Encoding HasBody Has the request/response body? Declaration public abstract bool HasBody { get; } Property Value Type Description Boolean Headers Collection of all headers. Declaration public HeaderCollection Headers { get; } Property Value Type Description HeaderCollection HeaderText The header text. Declaration public abstract string HeaderText { get; } Property Value Type Description String HttpVersion Http Version. Declaration public Version HttpVersion { get; set; } Property Value Type Description Version IsBodyRead Was the body read by user? Declaration public bool IsBodyRead { get; } Property Value Type Description Boolean IsChunked Is body send as chunked bytes. Declaration public bool IsChunked { get; set; } Property Value Type Description Boolean KeepBody Keeps the body data after the session is finished. Declaration public bool KeepBody { get; set; } Property Value Type Description Boolean Methods ToString() Declaration public override string ToString() Returns Type Description String Overrides Object.ToString()" }, "api/Titanium.Web.Proxy.Http.Response.html": { "href": "api/Titanium.Web.Proxy.Http.Response.html", @@ -142,7 +142,7 @@ "api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html": { "href": "api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html", "title": "Class RedirectResponse | Titanium Web Proxy", - "keywords": "Class RedirectResponse Redirect response Inheritance Object RequestResponseBase Response RedirectResponse Inherited Members Response.StatusCode Response.StatusDescription Response.HasBody Response.KeepAlive Response.Is100Continue Response.ExpectationFailed Response.HeaderText RequestResponseBase.BodyInternal RequestResponseBase.KeepBody RequestResponseBase.HttpVersion RequestResponseBase.Headers RequestResponseBase.ContentLength RequestResponseBase.ContentEncoding RequestResponseBase.Encoding RequestResponseBase.ContentType RequestResponseBase.IsChunked RequestResponseBase.Body RequestResponseBase.BodyString RequestResponseBase.IsBodyRead RequestResponseBase.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Http.Responses Assembly : Titanium.Web.Proxy.dll Syntax public sealed class RedirectResponse : Response Constructors RedirectResponse() Constructor. Declaration public RedirectResponse()" + "keywords": "Class RedirectResponse Redirect response Inheritance Object RequestResponseBase Response RedirectResponse Inherited Members Response.StatusCode Response.StatusDescription Response.HasBody Response.KeepAlive Response.Is100Continue Response.ExpectationFailed Response.HeaderText RequestResponseBase.BodyInternal RequestResponseBase.KeepBody RequestResponseBase.HttpVersion RequestResponseBase.Headers RequestResponseBase.ContentLength RequestResponseBase.ContentEncoding RequestResponseBase.Encoding RequestResponseBase.ContentType RequestResponseBase.IsChunked RequestResponseBase.Body RequestResponseBase.BodyString RequestResponseBase.IsBodyRead RequestResponseBase.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Http.Responses Assembly : Titanium.Web.Proxy.dll Syntax public sealed class RedirectResponse : Response Constructors RedirectResponse() Initializes a new instance of the RedirectResponse class. Declaration public RedirectResponse()" }, "api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html": { "href": "api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html", diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index b3bb7bc4b..b3ffa94f8 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -1522,7 +1522,14 @@ references: - uid: Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal name: BodyInternal href: api/Titanium.Web.Proxy.Http.RequestResponseBase.html#Titanium_Web_Proxy_Http_RequestResponseBase_BodyInternal - commentId: F:Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal + commentId: P:Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal + fullName: Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal + nameWithType: RequestResponseBase.BodyInternal +- uid: Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal* + name: BodyInternal + href: api/Titanium.Web.Proxy.Http.RequestResponseBase.html#Titanium_Web_Proxy_Http_RequestResponseBase_BodyInternal_ + commentId: Overload:Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal + isSpec: "True" fullName: Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal nameWithType: RequestResponseBase.BodyInternal - uid: Titanium.Web.Proxy.Http.RequestResponseBase.BodyString From 9f3e9d92f50a8050ea928f5af3e57e5bfe4202b0 Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 1 May 2018 15:01:32 +0200 Subject: [PATCH 11/23] alpn improvement --- Titanium.Web.Proxy/ExplicitClientHandler.cs | 12 ++++--- .../Extensions/SslExtensions.cs | 3 ++ .../Network/Tcp/TcpClientConnection.cs | 3 ++ .../Network/Tcp/TcpConnectionFactory.cs | 15 +++------ .../Network/Tcp/TcpServerConnection.cs | 3 +- Titanium.Web.Proxy/RequestHandler.cs | 31 ++++++++++++++++--- 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index c42668e7b..3a61932d3 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -136,9 +136,9 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, { // test server HTTP/2 support // todo: this is a hack, because Titanium does not support HTTP protocol changing currently - using (var connection = await GetServerConnection(connectArgs, true, cancellationToken)) + using (var connection = await GetServerConnection(connectArgs, true, SslExtensions.Http2ProtocolAsList, cancellationToken)) { - http2Supproted = connection.IsHttp2Supported; + http2Supproted = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2; } } @@ -170,6 +170,10 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck; await sslStream.AuthenticateAsServerAsync(options, cancellationToken); +#if NETCOREAPP2_1 + clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; +#endif + // HTTPS server created - we can now decrypt the client's traffic clientStream = new CustomBufferedStream(sslStream, BufferSize); @@ -197,7 +201,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response, if (!decryptSsl || !isClientHello) { // create new connection - using (var connection = await GetServerConnection(connectArgs, true, cancellationToken)) + using (var connection = await GetServerConnection(connectArgs, true, clientConnection.NegotiatedApplicationProtocol, cancellationToken)) { if (isClientHello) { @@ -261,7 +265,7 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, } // create new connection - using (var connection = await GetServerConnection(connectArgs, true, cancellationToken)) + using (var connection = await GetServerConnection(connectArgs, true, SslExtensions.Http2ProtocolAsList, cancellationToken)) { await connection.StreamWriter.WriteLineAsync("PRI * HTTP/2.0", cancellationToken); await connection.StreamWriter.WriteLineAsync(cancellationToken); diff --git a/Titanium.Web.Proxy/Extensions/SslExtensions.cs b/Titanium.Web.Proxy/Extensions/SslExtensions.cs index f9889cc52..71ecf1b48 100644 --- a/Titanium.Web.Proxy/Extensions/SslExtensions.cs +++ b/Titanium.Web.Proxy/Extensions/SslExtensions.cs @@ -14,6 +14,9 @@ internal static class SslExtensions internal static readonly List Http11ProtocolAsList = new List { SslApplicationProtocol.Http11 }; + internal static readonly List Http2ProtocolAsList = + new List { SslApplicationProtocol.Http2 }; + internal static string GetServerName(this ClientHelloInfo clientHelloInfo) { if (clientHelloInfo.Extensions != null && diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs b/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs index 11fe07000..8f20eb265 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Net; +using System.Net.Security; using System.Net.Sockets; using Titanium.Web.Proxy.Extensions; @@ -26,6 +27,8 @@ internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient) public EndPoint RemoteEndPoint => tcpClient.Client.RemoteEndPoint; + internal SslApplicationProtocol NegotiatedApplicationProtocol { get; set; } + private readonly TcpClient tcpClient; public Stream GetStream() diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs index 0b430b236..9b30f8c7f 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs @@ -23,9 +23,9 @@ internal class TcpConnectionFactory /// /// /// - /// /// /// + /// /// /// /// @@ -33,7 +33,7 @@ internal class TcpConnectionFactory /// /// internal async Task CreateClient(string remoteHostName, int remotePort, - List applicationProtocols, Version httpVersion, bool decryptSsl, bool isConnect, + Version httpVersion, bool decryptSsl, List applicationProtocols, bool isConnect, ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy, CancellationToken cancellationToken) { @@ -55,7 +55,7 @@ internal async Task CreateClient(string remoteHostName, int TcpClient tcpClient = null; CustomBufferedStream stream = null; - bool http2Supported = false; + SslApplicationProtocol negotiatedApplicationProtocol = default; try { @@ -114,18 +114,13 @@ internal async Task CreateClient(string remoteHostName, int var options = new SslClientAuthenticationOptions(); options.ApplicationProtocols = applicationProtocols; - if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0) - { - options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList; - } - options.TargetHost = remoteHostName; options.ClientCertificates = null; options.EnabledSslProtocols = proxyServer.SupportedSslProtocols; options.CertificateRevocationCheckMode = proxyServer.CheckCertificateRevocation; await sslStream.AuthenticateAsClientAsync(options, cancellationToken); #if NETCOREAPP2_1 - http2Supported = sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2; + negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; #endif } @@ -146,7 +141,7 @@ internal async Task CreateClient(string remoteHostName, int HostName = remoteHostName, Port = remotePort, IsHttps = decryptSsl, - IsHttp2Supported = http2Supported, + NegotiatedApplicationProtocol = negotiatedApplicationProtocol, UseUpstreamProxy = useUpstreamProxy, StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferSize), Stream = stream, diff --git a/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs b/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs index 1c18b28be..a0521d212 100644 --- a/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs +++ b/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Net.Security; using System.Net.Sockets; using StreamExtended.Network; using Titanium.Web.Proxy.Extensions; @@ -31,7 +32,7 @@ internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient) internal bool IsHttps { get; set; } - internal bool IsHttp2Supported { get; set; } + internal SslApplicationProtocol NegotiatedApplicationProtocol { get; set; } internal bool UseUpstreamProxy { get; set; } diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index bfd225db3..e74e6c7a4 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Net; +using System.Net.Security; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -179,7 +181,7 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response, if (serverConnection == null) { - serverConnection = await GetServerConnection(args, false, cancellationToken); + serverConnection = await GetServerConnection(args, false, clientConnection.NegotiatedApplicationProtocol, cancellationToken); } // if upgrading to websocket then relay the requet without reading the contents @@ -353,10 +355,31 @@ await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent /// /// The session event arguments. /// Is this a CONNECT request. + /// + /// The cancellation token for this async task. + /// + private Task GetServerConnection(SessionEventArgsBase args, bool isConnect, + SslApplicationProtocol applicationProtocol, CancellationToken cancellationToken) + { + List applicationProtocols = null; + if (applicationProtocol != default) + { + applicationProtocols = new List { applicationProtocol }; + } + + return GetServerConnection(args, isConnect, applicationProtocols, cancellationToken); + } + + /// + /// Create a server connection. + /// + /// The session event arguments. + /// Is this a CONNECT request. + /// /// The cancellation token for this async task. /// private async Task GetServerConnection(SessionEventArgsBase args, bool isConnect, - CancellationToken cancellationToken) + List applicationProtocols, CancellationToken cancellationToken) { ExternalProxy customUpStreamProxy = null; @@ -371,8 +394,8 @@ private async Task GetServerConnection(SessionEventArgsBase return await tcpConnectionFactory.CreateClient( args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, - args.WebSession.ConnectRequest?.ClientHelloInfo?.GetAlpn(), - args.WebSession.Request.HttpVersion, isHttps, isConnect, + args.WebSession.Request.HttpVersion, + isHttps, applicationProtocols, isConnect, this, args.WebSession.UpStreamEndPoint ?? UpStreamEndPoint, customUpStreamProxy ?? (isHttps ? UpStreamHttpsProxy : UpStreamHttpProxy), cancellationToken); From 5a7f46cec1c79d986bc57ce3dc0e52a828483887 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Tue, 1 May 2018 13:00:42 -0400 Subject: [PATCH 12/23] cleanup comments --- Titanium.Web.Proxy/ProxyServer.cs | 59 +++++++++++++++++++------------ 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index 1811867a2..692f9a127 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -19,8 +19,9 @@ namespace Titanium.Web.Proxy { + /// /// - /// This object is the backbone of proxy. One can create as many instances as needed. + /// This class is the backbone of proxy. One can create as many instances as needed. /// However care should be taken to avoid using the same listening ports across multiple instances. /// public partial class ProxyServer : IDisposable @@ -29,7 +30,6 @@ public partial class ProxyServer : IDisposable /// HTTP & HTTPS scheme shorthands. /// internal static readonly string UriSchemeHttp = Uri.UriSchemeHttp; - internal static readonly string UriSchemeHttps = Uri.UriSchemeHttps; /// @@ -57,6 +57,7 @@ public partial class ProxyServer : IDisposable /// private WinHttpWebProxyFinder systemProxyResolver; + /// /// /// Initializes a new instance of ProxyServer class with provided parameters. /// @@ -108,7 +109,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, } /// - /// An object that creates tcp connection to server. + /// An factory that creates tcp connection to server. /// private TcpConnectionFactory tcpConnectionFactory { get; } @@ -128,7 +129,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, public bool ForwardToUpstreamGateway { get; set; } /// - /// Enable disable Windows Authentication (NTLM/Kerberos) + /// Enable disable Windows Authentication (NTLM/Kerberos). /// Note: NTLM/Kerberos will always send local credentials of current user /// running the proxy process. This is because a man /// in middle attack with Windows domain authentication is not currently supported. @@ -144,6 +145,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, /// /// Does this proxy uses the HTTP protocol 100 continue behaviour strictly? /// Broken 100 contunue implementations on server/client may cause problems if enabled. + /// Defaults to false. /// public bool Enable100ContinueBehaviour { get; set; } @@ -225,12 +227,12 @@ public ExceptionHandler ExceptionFunc /// /// A callback to authenticate clients. /// Parameters are username and password as provided by client. - /// Return true for successful authentication. + /// Should return true for successful authentication. /// public Func> AuthenticateUserFunc { get; set; } /// - /// Dispose Proxy. + /// Dispose the Proxy instance. /// public void Dispose() { @@ -243,37 +245,37 @@ public void Dispose() } /// - /// Occurs when client connection count changed. + /// Event occurs when client connection count changed. /// public event EventHandler ClientConnectionCountChanged; /// - /// Occurs when server connection count changed. + /// Event occurs when server connection count changed. /// public event EventHandler ServerConnectionCountChanged; /// - /// Verifies the remote SSL certificate used for authentication. + /// Event to override the default verification logic of remote SSL certificate received during authentication. /// public event AsyncEventHandler ServerCertificateValidationCallback; /// - /// Callback to override client certificate selection during mutual SSL authentication. + /// Event to override client certificate selection during mutual SSL authentication. /// public event AsyncEventHandler ClientCertificateSelectionCallback; /// - /// Intercept request to server. + /// Intercept request event to server. /// public event AsyncEventHandler BeforeRequest; /// - /// Intercept response from server. + /// Intercept response event from server. /// public event AsyncEventHandler BeforeResponse; /// - /// Intercept after response from server. + /// Intercept after response event from server. /// public event AsyncEventHandler AfterResponse; @@ -299,7 +301,7 @@ public void AddEndPoint(ProxyEndPoint endPoint) /// /// Remove a proxy end point. - /// Will throw error if the end point does'nt exist + /// Will throw error if the end point does'nt exist. /// /// The existing endpoint to remove. public void RemoveEndPoint(ProxyEndPoint endPoint) @@ -320,7 +322,7 @@ public void RemoveEndPoint(ProxyEndPoint endPoint) /// /// Set the given explicit end point as the default proxy server for current machine. /// - /// + /// The explicit endpoint. public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint) { SetAsSystemProxy(endPoint, ProxyProtocolType.Http); @@ -329,7 +331,7 @@ public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint) /// /// Set the given explicit end point as the default proxy server for current machine. /// - /// + /// The explicit endpoint. public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) { SetAsSystemProxy(endPoint, ProxyProtocolType.Https); @@ -338,8 +340,8 @@ public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) /// /// Set the given explicit end point as the default proxy server for current machine. /// - /// - /// + /// The explicit endpoint. + /// The proxy protocol type. public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) { if (RunTime.IsRunningOnMono) @@ -472,7 +474,7 @@ public void Start() } // clear any system proxy settings which is pointing to our own endpoint (causing a cycle) - // due to non gracious proxy shutdown before or something else + // due to ungracious proxy shutdown before or something else if (systemProxySettingsManager != null && RunTime.IsWindows) { var proxyInfo = systemProxySettingsManager.GetProxyInfoFromRegistry(); @@ -602,8 +604,10 @@ private void ValidateEndPointAsSystemProxy(ExplicitProxyEndPoint endPoint) } /// - /// Gets the system up stream proxy. + /// Gets the system up stream proxy. /// + /// The session. + /// The external proxy as task result. private Task GetSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs) { var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri); @@ -645,6 +649,12 @@ private void OnAcceptConnection(IAsyncResult asyn) endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint); } + /// + /// Handle the client. + /// + /// The client. + /// The proxy endpoint. + /// The task. private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint) { tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; @@ -663,6 +673,11 @@ private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint) } } + /// + /// Handle exception. + /// + /// The client stream. + /// The exception. private void OnException(CustomBufferedStream clientStream, Exception exception) { #if DEBUG @@ -687,7 +702,7 @@ private void QuitListen(ProxyEndPoint endPoint) /// /// Update client connection count. /// - /// + /// Should we increment/decrement? internal void UpdateClientConnectionCount(bool increment) { if (increment) @@ -705,7 +720,7 @@ internal void UpdateClientConnectionCount(bool increment) /// /// Update server connection count. /// - /// + /// Should we increment/decrement? internal void UpdateServerConnectionCount(bool increment) { if (increment) From c2f86254076cbe20fb322e7bf5be201b70423b07 Mon Sep 17 00:00:00 2001 From: buildbot121 Date: Tue, 1 May 2018 10:03:57 -0700 Subject: [PATCH 13/23] API documentation update by build server --- docs/api/Titanium.Web.Proxy.ProxyServer.html | 39 +++++++++++--------- docs/api/Titanium.Web.Proxy.html | 2 +- docs/index.json | 4 +- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/docs/api/Titanium.Web.Proxy.ProxyServer.html b/docs/api/Titanium.Web.Proxy.ProxyServer.html index ab97230c4..2c50f8a2d 100644 --- a/docs/api/Titanium.Web.Proxy.ProxyServer.html +++ b/docs/api/Titanium.Web.Proxy.ProxyServer.html @@ -83,7 +83,7 @@

    Class ProxyServer

    -

    This object is the backbone of proxy. One can create as many instances as needed. +

    This class is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances.

    @@ -234,7 +234,7 @@

    Properties

    AuthenticateUserFunc

    A callback to authenticate clients. Parameters are username and password as provided by client. -Return true for successful authentication.

    +Should return true for successful authentication.

    Declaration
    @@ -392,7 +392,8 @@
    Property Value

    Enable100ContinueBehaviour

    Does this proxy uses the HTTP protocol 100 continue behaviour strictly? -Broken 100 contunue implementations on server/client may cause problems if enabled.

    +Broken 100 contunue implementations on server/client may cause problems if enabled. +Defaults to false.

    Declaration
    @@ -418,7 +419,7 @@
    Property Value

    EnableWinAuth

    -

    Enable disable Windows Authentication (NTLM/Kerberos) +

    Enable disable Windows Authentication (NTLM/Kerberos). Note: NTLM/Kerberos will always send local credentials of current user running the proxy process. This is because a man in middle attack with Windows domain authentication is not currently supported.

    @@ -827,7 +828,7 @@
    Parameters

    Dispose()

    -

    Dispose Proxy.

    +

    Dispose the Proxy instance.

    Declaration
    @@ -839,7 +840,7 @@
    Declaration

    RemoveEndPoint(ProxyEndPoint)

    Remove a proxy end point. -Will throw error if the end point does'nt exist

    +Will throw error if the end point does'nt exist.

    Declaration
    @@ -888,7 +889,8 @@
    Parameters
    - +
    ExplicitProxyEndPoint endPoint

    The explicit endpoint.

    +
    @@ -916,7 +918,8 @@
    Parameters
    ExplicitProxyEndPoint endPoint - +

    The explicit endpoint.

    + @@ -944,12 +947,14 @@
    Parameters
    ExplicitProxyEndPoint endPoint - +

    The explicit endpoint.

    + ProxyProtocolType protocolType - +

    The proxy protocol type.

    + @@ -980,7 +985,7 @@

    Events

    AfterResponse

    -

    Intercept after response from server.

    +

    Intercept after response event from server.

    Declaration
    @@ -1005,7 +1010,7 @@
    Event Type

    BeforeRequest

    -

    Intercept request to server.

    +

    Intercept request event to server.

    Declaration
    @@ -1030,7 +1035,7 @@
    Event Type

    BeforeResponse

    -

    Intercept response from server.

    +

    Intercept response event from server.

    Declaration
    @@ -1055,7 +1060,7 @@
    Event Type

    ClientCertificateSelectionCallback

    -

    Callback to override client certificate selection during mutual SSL authentication.

    +

    Event to override client certificate selection during mutual SSL authentication.

    Declaration
    @@ -1080,7 +1085,7 @@
    Event Type

    ClientConnectionCountChanged

    -

    Occurs when client connection count changed.

    +

    Event occurs when client connection count changed.

    Declaration
    @@ -1105,7 +1110,7 @@
    Event Type

    ServerCertificateValidationCallback

    -

    Verifies the remote SSL certificate used for authentication.

    +

    Event to override the default verification logic of remote SSL certificate received during authentication.

    Declaration
    @@ -1130,7 +1135,7 @@
    Event Type

    ServerConnectionCountChanged

    -

    Occurs when server connection count changed.

    +

    Event occurs when server connection count changed.

    Declaration
    diff --git a/docs/api/Titanium.Web.Proxy.html b/docs/api/Titanium.Web.Proxy.html index 8ecb83205..d39c071e1 100644 --- a/docs/api/Titanium.Web.Proxy.html +++ b/docs/api/Titanium.Web.Proxy.html @@ -88,7 +88,7 @@

    Nam

    Classes

    ProxyServer

    -

    This object is the backbone of proxy. One can create as many instances as needed. +

    This class is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances.

    Delegates diff --git a/docs/index.json b/docs/index.json index da5642ec3..00ac8e3c9 100644 --- a/docs/index.json +++ b/docs/index.json @@ -77,7 +77,7 @@ "api/Titanium.Web.Proxy.html": { "href": "api/Titanium.Web.Proxy.html", "title": "Namespace Titanium.Web.Proxy | Titanium Web Proxy", - "keywords": "Namespace Titanium.Web.Proxy Classes ProxyServer This object is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances. Delegates ExceptionHandler A delegate to catch exceptions occuring in proxy." + "keywords": "Namespace Titanium.Web.Proxy Classes ProxyServer This class is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances. Delegates ExceptionHandler A delegate to catch exceptions occuring in proxy." }, "api/Titanium.Web.Proxy.Http.ConnectRequest.html": { "href": "api/Titanium.Web.Proxy.Http.ConnectRequest.html", @@ -192,6 +192,6 @@ "api/Titanium.Web.Proxy.ProxyServer.html": { "href": "api/Titanium.Web.Proxy.ProxyServer.html", "title": "Class ProxyServer | Titanium Web Proxy", - "keywords": "Class ProxyServer This object is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances. Inheritance Object ProxyServer Implements IDisposable Inherited Members Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy Assembly : Titanium.Web.Proxy.dll Syntax public class ProxyServer : IDisposable Constructors ProxyServer(Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? ProxyServer(String, String, Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description String rootCertificateName Name of the root certificate. String rootCertificateIssuerName Name of the root certificate issuer. Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? Properties AuthenticateUserFunc A callback to authenticate clients. Parameters are username and password as provided by client. Return true for successful authentication. Declaration public Func> AuthenticateUserFunc { get; set; } Property Value Type Description Func < String , String , Task < Boolean >> BufferSize Buffer size used throughout this proxy. Declaration public int BufferSize { get; set; } Property Value Type Description Int32 CertificateManager Manages certificates used by this proxy. Declaration public CertificateManager CertificateManager { get; } Property Value Type Description CertificateManager CheckCertificateRevocation Should we check for certificare revocation during SSL authentication to servers Note: If enabled can reduce performance. Defaults to false. Declaration public X509RevocationMode CheckCertificateRevocation { get; set; } Property Value Type Description X509RevocationMode ClientConnectionCount Total number of active client connections. Declaration public int ClientConnectionCount { get; } Property Value Type Description Int32 ConnectionTimeOutSeconds Seconds client/server connection are to be kept alive when waiting for read/write to complete. Declaration public int ConnectionTimeOutSeconds { get; set; } Property Value Type Description Int32 Enable100ContinueBehaviour Does this proxy uses the HTTP protocol 100 continue behaviour strictly? Broken 100 contunue implementations on server/client may cause problems if enabled. Declaration public bool Enable100ContinueBehaviour { get; set; } Property Value Type Description Boolean EnableWinAuth Enable disable Windows Authentication (NTLM/Kerberos) Note: NTLM/Kerberos will always send local credentials of current user running the proxy process. This is because a man in middle attack with Windows domain authentication is not currently supported. Declaration public bool EnableWinAuth { get; set; } Property Value Type Description Boolean ExceptionFunc Callback for error events in this proxy instance. Declaration public ExceptionHandler ExceptionFunc { get; set; } Property Value Type Description ExceptionHandler ForwardToUpstreamGateway Gets or sets a value indicating whether requests will be chained to upstream gateway. Declaration public bool ForwardToUpstreamGateway { get; set; } Property Value Type Description Boolean GetCustomUpStreamProxyFunc A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests. User should return the ExternalProxy object with valid credentials. Declaration public Func> GetCustomUpStreamProxyFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , Task < ExternalProxy >> ProxyEndPoints A list of IpAddress and port this proxy is listening to. Declaration public List ProxyEndPoints { get; set; } Property Value Type Description List < ProxyEndPoint > ProxyRealm Realm used during Proxy Basic Authentication. Declaration public string ProxyRealm { get; set; } Property Value Type Description String ProxyRunning Is the proxy currently running? Declaration public bool ProxyRunning { get; } Property Value Type Description Boolean ServerConnectionCount Total number of active server connections. Declaration public int ServerConnectionCount { get; } Property Value Type Description Int32 SupportedSslProtocols List of supported Ssl versions. Declaration public SslProtocols SupportedSslProtocols { get; set; } Property Value Type Description SslProtocols UpStreamEndPoint Local adapter/NIC endpoint where proxy makes request via. Defaults via any IP addresses of this machine. Declaration public IPEndPoint UpStreamEndPoint { get; set; } Property Value Type Description IPEndPoint UpStreamHttpProxy External proxy used for Http requests. Declaration public ExternalProxy UpStreamHttpProxy { get; set; } Property Value Type Description ExternalProxy UpStreamHttpsProxy External proxy used for Https requests. Declaration public ExternalProxy UpStreamHttpsProxy { get; set; } Property Value Type Description ExternalProxy Methods AddEndPoint(ProxyEndPoint) Add a proxy end point. Declaration public void AddEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The proxy endpoint. DisableAllSystemProxies() Clear all proxy settings for current machine. Declaration public void DisableAllSystemProxies() DisableSystemHttpProxy() Clear HTTP proxy settings of current machine. Declaration public void DisableSystemHttpProxy() DisableSystemHttpsProxy() Clear HTTPS proxy settings of current machine. Declaration public void DisableSystemHttpsProxy() DisableSystemProxy(ProxyProtocolType) Clear the specified proxy setting for current machine. Declaration public void DisableSystemProxy(ProxyProtocolType protocolType) Parameters Type Name Description ProxyProtocolType protocolType Dispose() Dispose Proxy. Declaration public void Dispose() RemoveEndPoint(ProxyEndPoint) Remove a proxy end point. Will throw error if the end point does'nt exist Declaration public void RemoveEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The existing endpoint to remove. SetAsSystemHttpProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint SetAsSystemHttpsProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) Parameters Type Name Description ExplicitProxyEndPoint endPoint ProxyProtocolType protocolType Start() Start this proxy server instance. Declaration public void Start() Stop() Stop this proxy server instance. Declaration public void Stop() Events AfterResponse Intercept after response from server. Declaration public event AsyncEventHandler AfterResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > BeforeRequest Intercept request to server. Declaration public event AsyncEventHandler BeforeRequest Event Type Type Description AsyncEventHandler < SessionEventArgs > BeforeResponse Intercept response from server. Declaration public event AsyncEventHandler BeforeResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > ClientCertificateSelectionCallback Callback to override client certificate selection during mutual SSL authentication. Declaration public event AsyncEventHandler ClientCertificateSelectionCallback Event Type Type Description AsyncEventHandler < CertificateSelectionEventArgs > ClientConnectionCountChanged Occurs when client connection count changed. Declaration public event EventHandler ClientConnectionCountChanged Event Type Type Description EventHandler ServerCertificateValidationCallback Verifies the remote SSL certificate used for authentication. Declaration public event AsyncEventHandler ServerCertificateValidationCallback Event Type Type Description AsyncEventHandler < CertificateValidationEventArgs > ServerConnectionCountChanged Occurs when server connection count changed. Declaration public event EventHandler ServerConnectionCountChanged Event Type Type Description EventHandler Implements System.IDisposable" + "keywords": "Class ProxyServer This class is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances. Inheritance Object ProxyServer Implements IDisposable Inherited Members Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy Assembly : Titanium.Web.Proxy.dll Syntax public class ProxyServer : IDisposable Constructors ProxyServer(Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? ProxyServer(String, String, Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description String rootCertificateName Name of the root certificate. String rootCertificateIssuerName Name of the root certificate issuer. Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? Properties AuthenticateUserFunc A callback to authenticate clients. Parameters are username and password as provided by client. Should return true for successful authentication. Declaration public Func> AuthenticateUserFunc { get; set; } Property Value Type Description Func < String , String , Task < Boolean >> BufferSize Buffer size used throughout this proxy. Declaration public int BufferSize { get; set; } Property Value Type Description Int32 CertificateManager Manages certificates used by this proxy. Declaration public CertificateManager CertificateManager { get; } Property Value Type Description CertificateManager CheckCertificateRevocation Should we check for certificare revocation during SSL authentication to servers Note: If enabled can reduce performance. Defaults to false. Declaration public X509RevocationMode CheckCertificateRevocation { get; set; } Property Value Type Description X509RevocationMode ClientConnectionCount Total number of active client connections. Declaration public int ClientConnectionCount { get; } Property Value Type Description Int32 ConnectionTimeOutSeconds Seconds client/server connection are to be kept alive when waiting for read/write to complete. Declaration public int ConnectionTimeOutSeconds { get; set; } Property Value Type Description Int32 Enable100ContinueBehaviour Does this proxy uses the HTTP protocol 100 continue behaviour strictly? Broken 100 contunue implementations on server/client may cause problems if enabled. Defaults to false. Declaration public bool Enable100ContinueBehaviour { get; set; } Property Value Type Description Boolean EnableWinAuth Enable disable Windows Authentication (NTLM/Kerberos). Note: NTLM/Kerberos will always send local credentials of current user running the proxy process. This is because a man in middle attack with Windows domain authentication is not currently supported. Declaration public bool EnableWinAuth { get; set; } Property Value Type Description Boolean ExceptionFunc Callback for error events in this proxy instance. Declaration public ExceptionHandler ExceptionFunc { get; set; } Property Value Type Description ExceptionHandler ForwardToUpstreamGateway Gets or sets a value indicating whether requests will be chained to upstream gateway. Declaration public bool ForwardToUpstreamGateway { get; set; } Property Value Type Description Boolean GetCustomUpStreamProxyFunc A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests. User should return the ExternalProxy object with valid credentials. Declaration public Func> GetCustomUpStreamProxyFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , Task < ExternalProxy >> ProxyEndPoints A list of IpAddress and port this proxy is listening to. Declaration public List ProxyEndPoints { get; set; } Property Value Type Description List < ProxyEndPoint > ProxyRealm Realm used during Proxy Basic Authentication. Declaration public string ProxyRealm { get; set; } Property Value Type Description String ProxyRunning Is the proxy currently running? Declaration public bool ProxyRunning { get; } Property Value Type Description Boolean ServerConnectionCount Total number of active server connections. Declaration public int ServerConnectionCount { get; } Property Value Type Description Int32 SupportedSslProtocols List of supported Ssl versions. Declaration public SslProtocols SupportedSslProtocols { get; set; } Property Value Type Description SslProtocols UpStreamEndPoint Local adapter/NIC endpoint where proxy makes request via. Defaults via any IP addresses of this machine. Declaration public IPEndPoint UpStreamEndPoint { get; set; } Property Value Type Description IPEndPoint UpStreamHttpProxy External proxy used for Http requests. Declaration public ExternalProxy UpStreamHttpProxy { get; set; } Property Value Type Description ExternalProxy UpStreamHttpsProxy External proxy used for Https requests. Declaration public ExternalProxy UpStreamHttpsProxy { get; set; } Property Value Type Description ExternalProxy Methods AddEndPoint(ProxyEndPoint) Add a proxy end point. Declaration public void AddEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The proxy endpoint. DisableAllSystemProxies() Clear all proxy settings for current machine. Declaration public void DisableAllSystemProxies() DisableSystemHttpProxy() Clear HTTP proxy settings of current machine. Declaration public void DisableSystemHttpProxy() DisableSystemHttpsProxy() Clear HTTPS proxy settings of current machine. Declaration public void DisableSystemHttpsProxy() DisableSystemProxy(ProxyProtocolType) Clear the specified proxy setting for current machine. Declaration public void DisableSystemProxy(ProxyProtocolType protocolType) Parameters Type Name Description ProxyProtocolType protocolType Dispose() Dispose the Proxy instance. Declaration public void Dispose() RemoveEndPoint(ProxyEndPoint) Remove a proxy end point. Will throw error if the end point does'nt exist. Declaration public void RemoveEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The existing endpoint to remove. SetAsSystemHttpProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. SetAsSystemHttpsProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. ProxyProtocolType protocolType The proxy protocol type. Start() Start this proxy server instance. Declaration public void Start() Stop() Stop this proxy server instance. Declaration public void Stop() Events AfterResponse Intercept after response event from server. Declaration public event AsyncEventHandler AfterResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > BeforeRequest Intercept request event to server. Declaration public event AsyncEventHandler BeforeRequest Event Type Type Description AsyncEventHandler < SessionEventArgs > BeforeResponse Intercept response event from server. Declaration public event AsyncEventHandler BeforeResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > ClientCertificateSelectionCallback Event to override client certificate selection during mutual SSL authentication. Declaration public event AsyncEventHandler ClientCertificateSelectionCallback Event Type Type Description AsyncEventHandler < CertificateSelectionEventArgs > ClientConnectionCountChanged Event occurs when client connection count changed. Declaration public event EventHandler ClientConnectionCountChanged Event Type Type Description EventHandler ServerCertificateValidationCallback Event to override the default verification logic of remote SSL certificate received during authentication. Declaration public event AsyncEventHandler ServerCertificateValidationCallback Event Type Type Description AsyncEventHandler < CertificateValidationEventArgs > ServerConnectionCountChanged Event occurs when server connection count changed. Declaration public event EventHandler ServerConnectionCountChanged Event Type Type Description EventHandler Implements System.IDisposable" } } From 348e14aed5dca95c64908d6f329276571874eea4 Mon Sep 17 00:00:00 2001 From: Honfika Date: Sun, 6 May 2018 12:27:51 +0200 Subject: [PATCH 14/23] race condition fix, #424 --- Titanium.Web.Proxy/ProxyServer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index 692f9a127..5a0e0dbda 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -509,17 +509,17 @@ public void Start() ProxyRunning = true; - foreach (var endPoint in ProxyEndPoints) - { - Listen(endPoint); - } - CertificateManager.ClearIdleCertificates(); if (RunTime.IsWindows && !RunTime.IsRunningOnMono) { WinAuthEndPoint.ClearIdleStates(2); } + + foreach (var endPoint in ProxyEndPoints) + { + Listen(endPoint); + } } /// From d148f77091cbc7fb5b69c1d651b098e2be72b21c Mon Sep 17 00:00:00 2001 From: buildbot121 Date: Sun, 6 May 2018 03:29:57 -0700 Subject: [PATCH 15/23] API documentation update by build server --- .../Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html | 2 +- ...eb.Proxy.EventArguments.BeforeSslAuthenticateEventArgs.html | 2 +- ...Web.Proxy.EventArguments.CertificateSelectionEventArgs.html | 2 +- ...eb.Proxy.EventArguments.CertificateValidationEventArgs.html | 2 +- ...Proxy.EventArguments.MultipartRequestPartSentEventArgs.html | 2 +- .../Titanium.Web.Proxy.EventArguments.SessionEventArgs.html | 2 +- ...Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html | 2 +- ...Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html | 2 +- docs/api/Titanium.Web.Proxy.EventArguments.html | 2 +- docs/api/Titanium.Web.Proxy.ExceptionHandler.html | 2 +- .../Titanium.Web.Proxy.Exceptions.BodyNotFoundException.html | 2 +- ...anium.Web.Proxy.Exceptions.ProxyAuthorizationException.html | 2 +- docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html | 2 +- docs/api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html | 2 +- docs/api/Titanium.Web.Proxy.Exceptions.html | 2 +- docs/api/Titanium.Web.Proxy.Http.ConnectRequest.html | 2 +- docs/api/Titanium.Web.Proxy.Http.ConnectResponse.html | 2 +- docs/api/Titanium.Web.Proxy.Http.HeaderCollection.html | 2 +- docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html | 2 +- docs/api/Titanium.Web.Proxy.Http.KnownHeaders.html | 2 +- docs/api/Titanium.Web.Proxy.Http.Request.html | 2 +- docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html | 2 +- docs/api/Titanium.Web.Proxy.Http.Response.html | 2 +- .../api/Titanium.Web.Proxy.Http.Responses.GenericResponse.html | 2 +- docs/api/Titanium.Web.Proxy.Http.Responses.OkResponse.html | 2 +- .../Titanium.Web.Proxy.Http.Responses.RedirectResponse.html | 2 +- docs/api/Titanium.Web.Proxy.Http.Responses.html | 2 +- docs/api/Titanium.Web.Proxy.Http.html | 2 +- docs/api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html | 2 +- docs/api/Titanium.Web.Proxy.Models.ExternalProxy.html | 2 +- docs/api/Titanium.Web.Proxy.Models.HttpHeader.html | 2 +- docs/api/Titanium.Web.Proxy.Models.ProxyEndPoint.html | 2 +- .../Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html | 2 +- docs/api/Titanium.Web.Proxy.Models.html | 2 +- docs/api/Titanium.Web.Proxy.Network.CertificateEngine.html | 2 +- docs/api/Titanium.Web.Proxy.Network.CertificateManager.html | 2 +- docs/api/Titanium.Web.Proxy.Network.html | 2 +- docs/api/Titanium.Web.Proxy.ProxyServer.html | 2 +- docs/api/Titanium.Web.Proxy.html | 2 +- docs/styles/docfx.js | 3 ++- 40 files changed, 41 insertions(+), 40 deletions(-) diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html b/docs/api/Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html index d9dcc1467..d3f5eeae3 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.BeforeSslAuthenticateEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.BeforeSslAuthenticateEventArgs.html index 417ac3283..fab1e3831 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.BeforeSslAuthenticateEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.BeforeSslAuthenticateEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.html index bd886b46d..1a6c6aa9a 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.CertificateValidationEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.CertificateValidationEventArgs.html index 23ae152a0..41773346c 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.CertificateValidationEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.CertificateValidationEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html index a4a142b71..7db0ef5fe 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.MultipartRequestPartSentEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html index c4a398336..d930ec849 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html index 32e7d608b..15de2858c 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html index 5123f57c5..7182707e0 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.html b/docs/api/Titanium.Web.Proxy.EventArguments.html index 848a7870f..275102087 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.ExceptionHandler.html b/docs/api/Titanium.Web.Proxy.ExceptionHandler.html index c3ee94ce8..ff865ada7 100644 --- a/docs/api/Titanium.Web.Proxy.ExceptionHandler.html +++ b/docs/api/Titanium.Web.Proxy.ExceptionHandler.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Exceptions.BodyNotFoundException.html b/docs/api/Titanium.Web.Proxy.Exceptions.BodyNotFoundException.html index 779b6066f..8240a235c 100644 --- a/docs/api/Titanium.Web.Proxy.Exceptions.BodyNotFoundException.html +++ b/docs/api/Titanium.Web.Proxy.Exceptions.BodyNotFoundException.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyAuthorizationException.html b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyAuthorizationException.html index 40c586c51..aebb4e377 100644 --- a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyAuthorizationException.html +++ b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyAuthorizationException.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html index 08222fbca..c56f84128 100644 --- a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html +++ b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyException.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html index 9648e01d1..848b2b2da 100644 --- a/docs/api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html +++ b/docs/api/Titanium.Web.Proxy.Exceptions.ProxyHttpException.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Exceptions.html b/docs/api/Titanium.Web.Proxy.Exceptions.html index 97927cb6b..9a2cbe5ce 100644 --- a/docs/api/Titanium.Web.Proxy.Exceptions.html +++ b/docs/api/Titanium.Web.Proxy.Exceptions.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.ConnectRequest.html b/docs/api/Titanium.Web.Proxy.Http.ConnectRequest.html index e71ea592a..10db78f0b 100644 --- a/docs/api/Titanium.Web.Proxy.Http.ConnectRequest.html +++ b/docs/api/Titanium.Web.Proxy.Http.ConnectRequest.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.ConnectResponse.html b/docs/api/Titanium.Web.Proxy.Http.ConnectResponse.html index c920436e7..d87f24d9e 100644 --- a/docs/api/Titanium.Web.Proxy.Http.ConnectResponse.html +++ b/docs/api/Titanium.Web.Proxy.Http.ConnectResponse.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.HeaderCollection.html b/docs/api/Titanium.Web.Proxy.Http.HeaderCollection.html index d53597dc3..e89c9680c 100644 --- a/docs/api/Titanium.Web.Proxy.Http.HeaderCollection.html +++ b/docs/api/Titanium.Web.Proxy.Http.HeaderCollection.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html b/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html index 8f2627cfa..aea1435ba 100644 --- a/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html +++ b/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.KnownHeaders.html b/docs/api/Titanium.Web.Proxy.Http.KnownHeaders.html index d31635f0b..62588940b 100644 --- a/docs/api/Titanium.Web.Proxy.Http.KnownHeaders.html +++ b/docs/api/Titanium.Web.Proxy.Http.KnownHeaders.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.Request.html b/docs/api/Titanium.Web.Proxy.Http.Request.html index 004782e2d..36e68d3f5 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Request.html +++ b/docs/api/Titanium.Web.Proxy.Http.Request.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html b/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html index 0075c6a26..b1324bf3c 100644 --- a/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html +++ b/docs/api/Titanium.Web.Proxy.Http.RequestResponseBase.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.Response.html b/docs/api/Titanium.Web.Proxy.Http.Response.html index d8e13d032..d12b40e98 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Response.html +++ b/docs/api/Titanium.Web.Proxy.Http.Response.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.Responses.GenericResponse.html b/docs/api/Titanium.Web.Proxy.Http.Responses.GenericResponse.html index 0c03758c5..9a151112d 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Responses.GenericResponse.html +++ b/docs/api/Titanium.Web.Proxy.Http.Responses.GenericResponse.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.Responses.OkResponse.html b/docs/api/Titanium.Web.Proxy.Http.Responses.OkResponse.html index 3556c000a..5d306f197 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Responses.OkResponse.html +++ b/docs/api/Titanium.Web.Proxy.Http.Responses.OkResponse.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html b/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html index 500062082..39904d8c3 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html +++ b/docs/api/Titanium.Web.Proxy.Http.Responses.RedirectResponse.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.Responses.html b/docs/api/Titanium.Web.Proxy.Http.Responses.html index 10f6394b1..646a9499f 100644 --- a/docs/api/Titanium.Web.Proxy.Http.Responses.html +++ b/docs/api/Titanium.Web.Proxy.Http.Responses.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Http.html b/docs/api/Titanium.Web.Proxy.Http.html index b5e703faf..429746958 100644 --- a/docs/api/Titanium.Web.Proxy.Http.html +++ b/docs/api/Titanium.Web.Proxy.Http.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html b/docs/api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html index 173794e79..67e3c8612 100644 --- a/docs/api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html +++ b/docs/api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Models.ExternalProxy.html b/docs/api/Titanium.Web.Proxy.Models.ExternalProxy.html index 31e8e6862..e8a9bf344 100644 --- a/docs/api/Titanium.Web.Proxy.Models.ExternalProxy.html +++ b/docs/api/Titanium.Web.Proxy.Models.ExternalProxy.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Models.HttpHeader.html b/docs/api/Titanium.Web.Proxy.Models.HttpHeader.html index e375fe7dc..8ecf7b528 100644 --- a/docs/api/Titanium.Web.Proxy.Models.HttpHeader.html +++ b/docs/api/Titanium.Web.Proxy.Models.HttpHeader.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Models.ProxyEndPoint.html b/docs/api/Titanium.Web.Proxy.Models.ProxyEndPoint.html index 17be3710a..5226f09a1 100644 --- a/docs/api/Titanium.Web.Proxy.Models.ProxyEndPoint.html +++ b/docs/api/Titanium.Web.Proxy.Models.ProxyEndPoint.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html b/docs/api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html index 06ac33c4d..b7f06dddd 100644 --- a/docs/api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html +++ b/docs/api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Models.html b/docs/api/Titanium.Web.Proxy.Models.html index 9ebf7b913..2d9fb7190 100644 --- a/docs/api/Titanium.Web.Proxy.Models.html +++ b/docs/api/Titanium.Web.Proxy.Models.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Network.CertificateEngine.html b/docs/api/Titanium.Web.Proxy.Network.CertificateEngine.html index 8c2dbc8ec..a1e8e1c52 100644 --- a/docs/api/Titanium.Web.Proxy.Network.CertificateEngine.html +++ b/docs/api/Titanium.Web.Proxy.Network.CertificateEngine.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Network.CertificateManager.html b/docs/api/Titanium.Web.Proxy.Network.CertificateManager.html index de2053389..96aef6b1d 100644 --- a/docs/api/Titanium.Web.Proxy.Network.CertificateManager.html +++ b/docs/api/Titanium.Web.Proxy.Network.CertificateManager.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.Network.html b/docs/api/Titanium.Web.Proxy.Network.html index dbb4d576c..b68809db4 100644 --- a/docs/api/Titanium.Web.Proxy.Network.html +++ b/docs/api/Titanium.Web.Proxy.Network.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.ProxyServer.html b/docs/api/Titanium.Web.Proxy.ProxyServer.html index 2c50f8a2d..4e684f462 100644 --- a/docs/api/Titanium.Web.Proxy.ProxyServer.html +++ b/docs/api/Titanium.Web.Proxy.ProxyServer.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/Titanium.Web.Proxy.html b/docs/api/Titanium.Web.Proxy.html index d39c071e1..1ec151351 100644 --- a/docs/api/Titanium.Web.Proxy.html +++ b/docs/api/Titanium.Web.Proxy.html @@ -10,7 +10,7 @@ - + diff --git a/docs/styles/docfx.js b/docs/styles/docfx.js index d415cd0e7..32ce9f4ff 100644 --- a/docs/styles/docfx.js +++ b/docs/styles/docfx.js @@ -855,7 +855,8 @@ $(function () { state.selectedTabs.splice(index, 1); } } - firstVisibleTab.selected = true; + var tab = firstVisibleTab; + tab.selected = true; state.selectedTabs.push(tab.tabIds[0]); } } From 9139ab26eba4e938341615c07b6af741d902b8ba Mon Sep 17 00:00:00 2001 From: Honfika Date: Sun, 6 May 2018 13:05:27 +0200 Subject: [PATCH 16/23] Use of Guid as a session identifer #427 --- .../ProxyTestController.cs | 8 +- .../WinAuthTests.cs | 3 +- .../EventArguments/SessionEventArgsBase.cs | 10 +- Titanium.Web.Proxy/ExplicitClientHandler.cs | 4 +- .../Helpers/{Tcp.cs => TcpHelper.cs} | 604 ++++++++---------- Titanium.Web.Proxy/Http/HttpWebClient.cs | 11 +- Titanium.Web.Proxy/Http/InternalDataStore.cs | 27 + .../WinAuth/Security/WinAuthEndPoint.cs | 53 +- .../Network/WinAuth/WinAuthHandler.cs | 15 +- Titanium.Web.Proxy/ProxyServer.cs | 5 - Titanium.Web.Proxy/ResponseHandler.cs | 2 +- Titanium.Web.Proxy/WinAuthHandler.cs | 6 +- 12 files changed, 339 insertions(+), 409 deletions(-) rename Titanium.Web.Proxy/Helpers/{Tcp.cs => TcpHelper.cs} (70%) create mode 100644 Titanium.Web.Proxy/Http/InternalDataStore.cs diff --git a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs index 1c2556a05..348fb8adb 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs +++ b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs @@ -164,8 +164,12 @@ private async Task OnRequest(object sender, SessionEventArgs e) WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount); WriteToConsole(e.WebSession.Request.Url); + // create custom id for the request and store it in the UserData property + // It can be a simple integer, Guid, or any type + e.UserData = Guid.NewGuid(); + // read request headers - requestHeaderHistory[e.Id] = e.WebSession.Request.Headers; + requestHeaderHistory[(Guid)e.UserData] = e.WebSession.Request.Headers; ////This sample shows how to get the multipart form data headers //if (e.WebSession.Request.Host == "mail.yahoo.com" && e.WebSession.Request.IsMultipartFormData) @@ -221,7 +225,7 @@ private async Task OnResponse(object sender, SessionEventArgs e) { WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount); - var ext = System.IO.Path.GetExtension(e.WebSession.Request.RequestUri.AbsolutePath); + string ext = System.IO.Path.GetExtension(e.WebSession.Request.RequestUri.AbsolutePath); //if (ext == ".gif" || ext == ".png" || ext == ".jpg") //{ diff --git a/Tests/Titanium.Web.Proxy.UnitTests/WinAuthTests.cs b/Tests/Titanium.Web.Proxy.UnitTests/WinAuthTests.cs index 6a5d196e5..fd9c9f4aa 100644 --- a/Tests/Titanium.Web.Proxy.UnitTests/WinAuthTests.cs +++ b/Tests/Titanium.Web.Proxy.UnitTests/WinAuthTests.cs @@ -1,5 +1,6 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Network.WinAuth; namespace Titanium.Web.Proxy.UnitTests @@ -10,7 +11,7 @@ public class WinAuthTests [TestMethod] public void Test_Acquire_Client_Token() { - string token = WinAuthHandler.GetInitialAuthToken("mylocalserver.com", "NTLM", Guid.NewGuid()); + string token = WinAuthHandler.GetInitialAuthToken("mylocalserver.com", "NTLM", new InternalDataStore()); Assert.IsTrue(token.Length > 1); } } diff --git a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index cfc7b8b59..221760b5a 100644 --- a/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -74,10 +74,14 @@ protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, internal ProxyClient ProxyClient { get; } /// - /// Returns a unique Id for this request/response session which is - /// same as the RequestId of WebSession. + /// Returns a user data for this request/response session which is + /// same as the user data of WebSession. /// - public Guid Id => WebSession.RequestId; + public object UserData + { + get => WebSession.UserData; + set => WebSession.UserData = value; + } /// /// Does this session uses SSL? diff --git a/Titanium.Web.Proxy/ExplicitClientHandler.cs b/Titanium.Web.Proxy/ExplicitClientHandler.cs index 3a61932d3..0ebbb1f23 100644 --- a/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -272,10 +272,12 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, await connection.StreamWriter.WriteLineAsync("SM", cancellationToken); await connection.StreamWriter.WriteLineAsync(cancellationToken); - await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, +#if NETCOREAPP2_1 + await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferSize, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); +#endif } } } diff --git a/Titanium.Web.Proxy/Helpers/Tcp.cs b/Titanium.Web.Proxy/Helpers/TcpHelper.cs similarity index 70% rename from Titanium.Web.Proxy/Helpers/Tcp.cs rename to Titanium.Web.Proxy/Helpers/TcpHelper.cs index 010490544..98471ac93 100644 --- a/Titanium.Web.Proxy/Helpers/Tcp.cs +++ b/Titanium.Web.Proxy/Helpers/TcpHelper.cs @@ -1,346 +1,258 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using StreamExtended.Helpers; -using Titanium.Web.Proxy.Extensions; - -namespace Titanium.Web.Proxy.Helpers -{ - internal enum IpVersion - { - Ipv4 = 1, - Ipv6 = 2 - } - - internal class TcpHelper - { - /// - /// Gets the process id by local port number. - /// - /// Process id. - internal static unsafe int GetProcessIdByLocalPort(IpVersion ipVersion, int localPort) - { - var tcpTable = IntPtr.Zero; - int tcpTableLength = 0; - - int ipVersionValue = ipVersion == IpVersion.Ipv4 ? NativeMethods.AfInet : NativeMethods.AfInet6; - const int allPid = (int)NativeMethods.TcpTableType.OwnerPidAll; - - if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, ipVersionValue, allPid, 0) != 0) - { - try - { - tcpTable = Marshal.AllocHGlobal(tcpTableLength); - if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, allPid, - 0) == 0) - { - int rowCount = *(int*)tcpTable; - uint portInNetworkByteOrder = ToNetworkByteOrder((uint)localPort); - - if (ipVersion == IpVersion.Ipv4) - { - var rowPtr = (NativeMethods.TcpRow*)(tcpTable + 4); - - for (int i = 0; i < rowCount; ++i) - { - if (rowPtr->localPort == portInNetworkByteOrder) - { - return rowPtr->owningPid; - } - - rowPtr++; - } - } - else - { - var rowPtr = (NativeMethods.Tcp6Row*)(tcpTable + 4); - - for (int i = 0; i < rowCount; ++i) - { - if (rowPtr->localPort == portInNetworkByteOrder) - { - return rowPtr->owningPid; - } - - rowPtr++; - } - } - } - } - finally - { - if (tcpTable != IntPtr.Zero) - { - Marshal.FreeHGlobal(tcpTable); - } - } - } - - return 0; - } - - /// - /// Converts 32-bit integer from native byte order (little-endian) - /// to network byte order for port, - /// switches 0th and 1st bytes, and 2nd and 3rd bytes - /// - /// - /// - private static uint ToNetworkByteOrder(uint port) - { - return ((port >> 8) & 0x00FF00FFu) | ((port << 8) & 0xFF00FF00u); - } - - /// - /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers - /// as prefix - /// Usefull for websocket requests - /// Asynchronous Programming Model, which does not throw exceptions when the socket is closed - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal static async Task SendRawApm(Stream clientStream, Stream serverStream, int bufferSize, - Action onDataSend, Action onDataReceive, - CancellationTokenSource cancellationTokenSource, - ExceptionHandler exceptionFunc) - { - var taskCompletionSource = new TaskCompletionSource(); - cancellationTokenSource.Token.Register(() => taskCompletionSource.TrySetResult(true)); - - // Now async relay all server=>client & client=>server data - var clientBuffer = BufferPool.GetBuffer(bufferSize); - var serverBuffer = BufferPool.GetBuffer(bufferSize); - try - { - BeginRead(clientStream, serverStream, clientBuffer, onDataSend, cancellationTokenSource, exceptionFunc); - BeginRead(serverStream, clientStream, serverBuffer, onDataReceive, cancellationTokenSource, - exceptionFunc); - await taskCompletionSource.Task; - } - finally - { - BufferPool.ReturnBuffer(clientBuffer); - BufferPool.ReturnBuffer(serverBuffer); - } - } - - private static void BeginRead(Stream inputStream, Stream outputStream, byte[] buffer, - Action onCopy, CancellationTokenSource cancellationTokenSource, - ExceptionHandler exceptionFunc) - { - if (cancellationTokenSource.IsCancellationRequested) - { - return; - } - - bool readFlag = false; - var readCallback = (AsyncCallback)(ar => - { - if (cancellationTokenSource.IsCancellationRequested || readFlag) - { - return; - } - - readFlag = true; - - try - { - int read = inputStream.EndRead(ar); - if (read <= 0) - { - cancellationTokenSource.Cancel(); - return; - } - - onCopy?.Invoke(buffer, 0, read); - - var writeCallback = (AsyncCallback)(ar2 => - { - if (cancellationTokenSource.IsCancellationRequested) - { - return; - } - - try - { - outputStream.EndWrite(ar2); - BeginRead(inputStream, outputStream, buffer, onCopy, cancellationTokenSource, - exceptionFunc); - } - catch (IOException ex) - { - cancellationTokenSource.Cancel(); - exceptionFunc(ex); - } - }); - - outputStream.BeginWrite(buffer, 0, read, writeCallback, null); - } - catch (IOException ex) - { - cancellationTokenSource.Cancel(); - exceptionFunc(ex); - } - }); - - var readResult = inputStream.BeginRead(buffer, 0, buffer.Length, readCallback, null); - if (readResult.CompletedSynchronously) - { - readCallback(readResult); - } - } - - /// - /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers - /// as prefix - /// Usefull for websocket requests - /// Task-based Asynchronous Pattern - /// - /// - /// - /// - /// - /// - /// - /// - /// - private static async Task SendRawTap(Stream clientStream, Stream serverStream, int bufferSize, - Action onDataSend, Action onDataReceive, - CancellationTokenSource cancellationTokenSource, - ExceptionHandler exceptionFunc) - { - // Now async relay all server=>client & client=>server data - var sendRelay = - clientStream.CopyToAsync(serverStream, onDataSend, bufferSize, cancellationTokenSource.Token); - var receiveRelay = - serverStream.CopyToAsync(clientStream, onDataReceive, bufferSize, cancellationTokenSource.Token); - - await Task.WhenAny(sendRelay, receiveRelay); - cancellationTokenSource.Cancel(); - - await Task.WhenAll(sendRelay, receiveRelay); - } - - /// - /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers - /// as prefix - /// Usefull for websocket requests - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal static Task SendRaw(Stream clientStream, Stream serverStream, int bufferSize, - Action onDataSend, Action onDataReceive, - CancellationTokenSource cancellationTokenSource, - ExceptionHandler exceptionFunc) - { - // todo: fix APM mode - return SendRawTap(clientStream, serverStream, bufferSize, onDataSend, onDataReceive, - cancellationTokenSource, - exceptionFunc); - } - - /// - /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers - /// as prefix - /// Usefull for websocket requests - /// Task-based Asynchronous Pattern - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize, - Action onDataSend, Action onDataReceive, - CancellationTokenSource cancellationTokenSource, Guid connectionId, - ExceptionHandler exceptionFunc) - { - // Now async relay all server=>client & client=>server data - var sendRelay = - CopyHttp2FrameAsync(clientStream, serverStream, onDataSend, bufferSize, connectionId, - cancellationTokenSource.Token); - var receiveRelay = - CopyHttp2FrameAsync(serverStream, clientStream, onDataReceive, bufferSize, connectionId, - cancellationTokenSource.Token); - - await Task.WhenAny(sendRelay, receiveRelay); - cancellationTokenSource.Cancel(); - - await Task.WhenAll(sendRelay, receiveRelay); - } - - private static async Task CopyHttp2FrameAsync(Stream input, Stream output, Action onCopy, - int bufferSize, Guid connectionId, CancellationToken cancellationToken) - { - var headerBuffer = new byte[9]; - var buffer = new byte[32768]; - while (true) - { - int read = await ForceRead(input, headerBuffer, 0, 9, cancellationToken); - if (read != 9) - { - return; - } - - int length = (headerBuffer[0] << 16) + (headerBuffer[1] << 8) + headerBuffer[2]; - byte type = headerBuffer[3]; - byte flags = headerBuffer[4]; - int streamId = ((headerBuffer[5] & 0x7f) << 24) + (headerBuffer[6] << 16) + (headerBuffer[7] << 8) + - headerBuffer[8]; - - read = await ForceRead(input, buffer, 0, length, cancellationToken); - if (read != length) - { - return; - } - - await output.WriteAsync(headerBuffer, 0, headerBuffer.Length, cancellationToken); - await output.WriteAsync(buffer, 0, length, cancellationToken); - - /*using (var fs = new System.IO.FileStream($@"c:\11\{connectionId}.{streamId}.dat", FileMode.Append)) - { - fs.Write(headerBuffer, 0, headerBuffer.Length); - fs.Write(buffer, 0, length); - }*/ - } - } - - private static async Task ForceRead(Stream input, byte[] buffer, int offset, int bytesToRead, - CancellationToken cancellationToken) - { - int totalRead = 0; - while (bytesToRead > 0) - { - int read = await input.ReadAsync(buffer, offset, bytesToRead, cancellationToken); - if (read == -1) - { - break; - } - - totalRead += read; - bytesToRead -= read; - offset += read; - } - - return totalRead; - } - } -} +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using StreamExtended.Helpers; +using Titanium.Web.Proxy.Extensions; + +namespace Titanium.Web.Proxy.Helpers +{ + internal enum IpVersion + { + Ipv4 = 1, + Ipv6 = 2 + } + + internal class TcpHelper + { + /// + /// Gets the process id by local port number. + /// + /// Process id. + internal static unsafe int GetProcessIdByLocalPort(IpVersion ipVersion, int localPort) + { + var tcpTable = IntPtr.Zero; + int tcpTableLength = 0; + + int ipVersionValue = ipVersion == IpVersion.Ipv4 ? NativeMethods.AfInet : NativeMethods.AfInet6; + const int allPid = (int)NativeMethods.TcpTableType.OwnerPidAll; + + if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, ipVersionValue, allPid, 0) != 0) + { + try + { + tcpTable = Marshal.AllocHGlobal(tcpTableLength); + if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, allPid, + 0) == 0) + { + int rowCount = *(int*)tcpTable; + uint portInNetworkByteOrder = ToNetworkByteOrder((uint)localPort); + + if (ipVersion == IpVersion.Ipv4) + { + var rowPtr = (NativeMethods.TcpRow*)(tcpTable + 4); + + for (int i = 0; i < rowCount; ++i) + { + if (rowPtr->localPort == portInNetworkByteOrder) + { + return rowPtr->owningPid; + } + + rowPtr++; + } + } + else + { + var rowPtr = (NativeMethods.Tcp6Row*)(tcpTable + 4); + + for (int i = 0; i < rowCount; ++i) + { + if (rowPtr->localPort == portInNetworkByteOrder) + { + return rowPtr->owningPid; + } + + rowPtr++; + } + } + } + } + finally + { + if (tcpTable != IntPtr.Zero) + { + Marshal.FreeHGlobal(tcpTable); + } + } + } + + return 0; + } + + /// + /// Converts 32-bit integer from native byte order (little-endian) + /// to network byte order for port, + /// switches 0th and 1st bytes, and 2nd and 3rd bytes + /// + /// + /// + private static uint ToNetworkByteOrder(uint port) + { + return ((port >> 8) & 0x00FF00FFu) | ((port << 8) & 0xFF00FF00u); + } + + /// + /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers + /// as prefix + /// Usefull for websocket requests + /// Asynchronous Programming Model, which does not throw exceptions when the socket is closed + /// + /// + /// + /// + /// + /// + /// + /// + /// + internal static async Task SendRawApm(Stream clientStream, Stream serverStream, int bufferSize, + Action onDataSend, Action onDataReceive, + CancellationTokenSource cancellationTokenSource, + ExceptionHandler exceptionFunc) + { + var taskCompletionSource = new TaskCompletionSource(); + cancellationTokenSource.Token.Register(() => taskCompletionSource.TrySetResult(true)); + + // Now async relay all server=>client & client=>server data + var clientBuffer = BufferPool.GetBuffer(bufferSize); + var serverBuffer = BufferPool.GetBuffer(bufferSize); + try + { + BeginRead(clientStream, serverStream, clientBuffer, onDataSend, cancellationTokenSource, exceptionFunc); + BeginRead(serverStream, clientStream, serverBuffer, onDataReceive, cancellationTokenSource, + exceptionFunc); + await taskCompletionSource.Task; + } + finally + { + BufferPool.ReturnBuffer(clientBuffer); + BufferPool.ReturnBuffer(serverBuffer); + } + } + + private static void BeginRead(Stream inputStream, Stream outputStream, byte[] buffer, + Action onCopy, CancellationTokenSource cancellationTokenSource, + ExceptionHandler exceptionFunc) + { + if (cancellationTokenSource.IsCancellationRequested) + { + return; + } + + bool readFlag = false; + var readCallback = (AsyncCallback)(ar => + { + if (cancellationTokenSource.IsCancellationRequested || readFlag) + { + return; + } + + readFlag = true; + + try + { + int read = inputStream.EndRead(ar); + if (read <= 0) + { + cancellationTokenSource.Cancel(); + return; + } + + onCopy?.Invoke(buffer, 0, read); + + var writeCallback = (AsyncCallback)(ar2 => + { + if (cancellationTokenSource.IsCancellationRequested) + { + return; + } + + try + { + outputStream.EndWrite(ar2); + BeginRead(inputStream, outputStream, buffer, onCopy, cancellationTokenSource, + exceptionFunc); + } + catch (IOException ex) + { + cancellationTokenSource.Cancel(); + exceptionFunc(ex); + } + }); + + outputStream.BeginWrite(buffer, 0, read, writeCallback, null); + } + catch (IOException ex) + { + cancellationTokenSource.Cancel(); + exceptionFunc(ex); + } + }); + + var readResult = inputStream.BeginRead(buffer, 0, buffer.Length, readCallback, null); + if (readResult.CompletedSynchronously) + { + readCallback(readResult); + } + } + + /// + /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers + /// as prefix + /// Usefull for websocket requests + /// Task-based Asynchronous Pattern + /// + /// + /// + /// + /// + /// + /// + /// + /// + private static async Task SendRawTap(Stream clientStream, Stream serverStream, int bufferSize, + Action onDataSend, Action onDataReceive, + CancellationTokenSource cancellationTokenSource, + ExceptionHandler exceptionFunc) + { + // Now async relay all server=>client & client=>server data + var sendRelay = + clientStream.CopyToAsync(serverStream, onDataSend, bufferSize, cancellationTokenSource.Token); + var receiveRelay = + serverStream.CopyToAsync(clientStream, onDataReceive, bufferSize, cancellationTokenSource.Token); + + await Task.WhenAny(sendRelay, receiveRelay); + cancellationTokenSource.Cancel(); + + await Task.WhenAll(sendRelay, receiveRelay); + } + + /// + /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers + /// as prefix + /// Usefull for websocket requests + /// + /// + /// + /// + /// + /// + /// + /// + /// + internal static Task SendRaw(Stream clientStream, Stream serverStream, int bufferSize, + Action onDataSend, Action onDataReceive, + CancellationTokenSource cancellationTokenSource, + ExceptionHandler exceptionFunc) + { + // todo: fix APM mode + return SendRawTap(clientStream, serverStream, bufferSize, onDataSend, onDataReceive, + cancellationTokenSource, + exceptionFunc); + } + } +} diff --git a/Titanium.Web.Proxy/Http/HttpWebClient.cs b/Titanium.Web.Proxy/Http/HttpWebClient.cs index f461bdd11..1025b34f9 100644 --- a/Titanium.Web.Proxy/Http/HttpWebClient.cs +++ b/Titanium.Web.Proxy/Http/HttpWebClient.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Net; using System.Threading; @@ -20,7 +21,6 @@ internal HttpWebClient(int bufferSize, Request request = null, Response response { this.bufferSize = bufferSize; - RequestId = Guid.NewGuid(); Request = request ?? new Request(); Response = response ?? new Response(); } @@ -31,9 +31,14 @@ internal HttpWebClient(int bufferSize, Request request = null, Response response internal TcpServerConnection ServerConnection { get; set; } /// - /// Request ID. + /// Stores internal data for the session. /// - public Guid RequestId { get; } + internal InternalDataStore Data { get; } = new InternalDataStore(); + + /// + /// Gets or sets the user data. + /// + public object UserData { get; set; } /// /// Override UpStreamEndPoint for this request; Local NIC via request is made diff --git a/Titanium.Web.Proxy/Http/InternalDataStore.cs b/Titanium.Web.Proxy/Http/InternalDataStore.cs new file mode 100644 index 000000000..9111ad976 --- /dev/null +++ b/Titanium.Web.Proxy/Http/InternalDataStore.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Titanium.Web.Proxy.Http +{ + class InternalDataStore : Dictionary + { + public bool TryGetValueAs(string key, out T value) + { + bool result = TryGetValue(key, out var value1); + if (result) + { + value = (T)value1; + } + else + { + value = default; + } + + return result; + } + + public T GetAs(string key) + { + return (T)this[key]; + } + } +} \ No newline at end of file diff --git a/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs b/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs index 9e0847383..c4298c68e 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Security.Principal; using System.Threading.Tasks; +using Titanium.Web.Proxy.Http; namespace Titanium.Web.Proxy.Network.WinAuth.Security { @@ -14,19 +15,16 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security internal class WinAuthEndPoint { - /// - /// Keep track of auth states for reuse in final challenge response - /// - private static readonly IDictionary authStates = new ConcurrentDictionary(); - + private const string authStateKey = "AuthState"; + /// /// Acquire the intial client token to send /// /// /// - /// + /// /// - internal static byte[] AcquireInitialSecurityToken(string hostname, string authScheme, Guid requestId) + internal static byte[] AcquireInitialSecurityToken(string hostname, string authScheme, InternalDataStore data) { byte[] token; @@ -75,7 +73,7 @@ internal static byte[] AcquireInitialSecurityToken(string hostname, string authS state.AuthState = State.WinAuthState.INITIAL_TOKEN; token = clientToken.GetBytes(); - authStates.Add(requestId, state); + data.Add(authStateKey, state); } finally { @@ -91,9 +89,9 @@ internal static byte[] AcquireInitialSecurityToken(string hostname, string authS /// /// /// - /// + /// /// - internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverChallenge, Guid requestId) + internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverChallenge, InternalDataStore data) { byte[] token; @@ -104,7 +102,7 @@ internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverC try { - var state = authStates[requestId]; + var state = data.GetAs(authStateKey); state.UpdatePresence(); @@ -120,7 +118,7 @@ internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverC out clientToken, out NewContextAttributes, out NewLifeTime); - + if (result != SuccessfulResult) { return null; @@ -138,35 +136,16 @@ internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverC return token; } - /// - /// Clear any hanging states - /// - /// - internal static async void ClearIdleStates(int stateCacheTimeOutMinutes) - { - var cutOff = DateTime.Now.AddMinutes(-1 * stateCacheTimeOutMinutes); - - var outdated = authStates.Where(x => x.Value.LastSeen < cutOff).ToList(); - - foreach (var cache in outdated) - { - authStates.Remove(cache.Key); - } - - // after a minute come back to check for outdated certificates in cache - await Task.Delay(1000 * 60); - } - /// /// Validates that the current WinAuth state of the connection matches the /// expectation, used to detect failed authentication /// - /// + /// /// /// - internal static bool ValidateWinAuthState(Guid requestId, State.WinAuthState expectedAuthState) + internal static bool ValidateWinAuthState(InternalDataStore data, State.WinAuthState expectedAuthState) { - bool stateExists = authStates.TryGetValue(requestId, out var state); + bool stateExists = data.TryGetValueAs(authStateKey, out State state); if (expectedAuthState == State.WinAuthState.UNAUTHORIZED) { @@ -188,10 +167,10 @@ internal static bool ValidateWinAuthState(Guid requestId, State.WinAuthState exp /// /// Set the AuthState to authorized and update the connection state lifetime /// - /// - internal static void AuthenticatedResponse(Guid requestId) + /// + internal static void AuthenticatedResponse(InternalDataStore data) { - if (authStates.TryGetValue(requestId, out var state)) + if (data.TryGetValueAs(authStateKey, out State state)) { state.AuthState = State.WinAuthState.AUTHORIZED; state.UpdatePresence(); diff --git a/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs b/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs index c978299a4..94ec3d91a 100644 --- a/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs +++ b/Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs @@ -1,4 +1,5 @@ using System; +using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Network.WinAuth.Security; namespace Titanium.Web.Proxy.Network.WinAuth @@ -16,26 +17,26 @@ internal static class WinAuthHandler /// /// /// - /// + /// /// - internal static string GetInitialAuthToken(string serverHostname, string authScheme, Guid requestId) + internal static string GetInitialAuthToken(string serverHostname, string authScheme, InternalDataStore data) { - var tokenBytes = WinAuthEndPoint.AcquireInitialSecurityToken(serverHostname, authScheme, requestId); + var tokenBytes = WinAuthEndPoint.AcquireInitialSecurityToken(serverHostname, authScheme, data); return string.Concat(" ", Convert.ToBase64String(tokenBytes)); } - + /// /// Get the final token given the server challenge token /// /// /// - /// + /// /// - internal static string GetFinalAuthToken(string serverHostname, string serverToken, Guid requestId) + internal static string GetFinalAuthToken(string serverHostname, string serverToken, InternalDataStore data) { var tokenBytes = WinAuthEndPoint.AcquireFinalSecurityToken(serverHostname, Convert.FromBase64String(serverToken), - requestId); + data); return string.Concat(" ", Convert.ToBase64String(tokenBytes)); } diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs index 5a0e0dbda..467ce8e2d 100644 --- a/Titanium.Web.Proxy/ProxyServer.cs +++ b/Titanium.Web.Proxy/ProxyServer.cs @@ -511,11 +511,6 @@ public void Start() CertificateManager.ClearIdleCertificates(); - if (RunTime.IsWindows && !RunTime.IsRunningOnMono) - { - WinAuthEndPoint.ClearIdleStates(2); - } - foreach (var endPoint in ProxyEndPoints) { Listen(endPoint); diff --git a/Titanium.Web.Proxy/ResponseHandler.cs b/Titanium.Web.Proxy/ResponseHandler.cs index 2ab17ce93..ec07a200a 100644 --- a/Titanium.Web.Proxy/ResponseHandler.cs +++ b/Titanium.Web.Proxy/ResponseHandler.cs @@ -39,7 +39,7 @@ private async Task HandleHttpSessionResponse(SessionEventArgs args) } else { - WinAuthEndPoint.AuthenticatedResponse(args.WebSession.RequestId); + WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data); } } diff --git a/Titanium.Web.Proxy/WinAuthHandler.cs b/Titanium.Web.Proxy/WinAuthHandler.cs index 0559c66a4..4cc9f6a58 100644 --- a/Titanium.Web.Proxy/WinAuthHandler.cs +++ b/Titanium.Web.Proxy/WinAuthHandler.cs @@ -96,7 +96,7 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) var expectedAuthState = scheme == null ? State.WinAuthState.INITIAL_TOKEN : State.WinAuthState.UNAUTHORIZED; - if (!WinAuthEndPoint.ValidateWinAuthState(args.WebSession.RequestId, expectedAuthState)) + if (!WinAuthEndPoint.ValidateWinAuthState(args.WebSession.Data, expectedAuthState)) { // Invalid state, create proper error message to client await RewriteUnauthorizedResponse(args); @@ -111,7 +111,7 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) // initial value will match exactly any of the schemes if (scheme != null) { - string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host, scheme, args.Id); + string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host, scheme, args.WebSession.Data); string auth = string.Concat(scheme, clientToken); @@ -133,7 +133,7 @@ internal async Task Handle401UnAuthorized(SessionEventArgs args) authHeader.Value.Length > x.Length + 1); string serverToken = authHeader.Value.Substring(scheme.Length + 1); - string clientToken = WinAuthHandler.GetFinalAuthToken(request.Host, serverToken, args.Id); + string clientToken = WinAuthHandler.GetFinalAuthToken(request.Host, serverToken, args.WebSession.Data); string auth = string.Concat(scheme, clientToken); From 081d1b8cb44c8d50ae8414deff3dd878d1543e1f Mon Sep 17 00:00:00 2001 From: buildbot121 Date: Sun, 6 May 2018 04:07:52 -0700 Subject: [PATCH 17/23] API documentation update by build server --- ...Proxy.EventArguments.SessionEventArgs.html | 2 +- ...y.EventArguments.SessionEventArgsBase.html | 40 +++++++------- ...guments.TunnelConnectSessionEventArgs.html | 2 +- ...Titanium.Web.Proxy.Http.HttpWebClient.html | 30 +++++------ docs/index.json | 8 +-- docs/xrefmap.yml | 52 +++++++++---------- 6 files changed, 67 insertions(+), 67 deletions(-) diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html index d930ec849..cbf1ce847 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html @@ -109,7 +109,7 @@
    Inherited Members
    SessionEventArgsBase.ExceptionFunc

    SessionEventArgsBase.IsHttps diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html index 15de2858c..dcccf38ad 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html @@ -316,15 +316,14 @@
    Property Value
    - -

    Id

    -

    Returns a unique Id for this request/response session which is -same as the RequestId of WebSession.

    + +

    IsHttps

    +

    Does this session uses SSL?

    Declaration
    -
    public Guid Id { get; }
    +
    public bool IsHttps { get; }
    Property Value
    @@ -336,21 +335,21 @@
    Property Value
    - +
    GuidBoolean
    - -

    IsHttps

    -

    Does this session uses SSL?

    + +

    IsTransparent

    +

    Is this a transparent endpoint?

    Declaration
    -
    public bool IsHttps { get; }
    +
    public bool IsTransparent { get; }
    Property Value
    @@ -369,14 +368,14 @@
    Property Value
    - -

    IsTransparent

    -

    Is this a transparent endpoint?

    + +

    LocalEndPoint

    +

    Local endpoint via which we make the request.

    Declaration
    -
    public bool IsTransparent { get; }
    +
    public ProxyEndPoint LocalEndPoint { get; }
    Property Value
    @@ -388,21 +387,22 @@
    Property Value
    - +
    BooleanProxyEndPoint
    - -

    LocalEndPoint

    -

    Local endpoint via which we make the request.

    + +

    UserData

    +

    Returns a user data for this request/response session which is +same as the user data of WebSession.

    Declaration
    -
    public ProxyEndPoint LocalEndPoint { get; }
    +
    public object UserData { get; set; }
    Property Value
    @@ -414,7 +414,7 @@
    Property Value
    - + diff --git a/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html b/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html index 7182707e0..016e6cf14 100644 --- a/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html +++ b/docs/api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html @@ -106,7 +106,7 @@
    Inherited Members
    SessionEventArgsBase.ExceptionFunc
    SessionEventArgsBase.IsHttps diff --git a/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html b/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html index aea1435ba..c16451751 100644 --- a/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html +++ b/docs/api/Titanium.Web.Proxy.Http.HttpWebClient.html @@ -230,14 +230,14 @@
    Property Value
    ProxyEndPointObject
    - -

    RequestId

    -

    Request ID.

    + +

    Response

    +

    Web Response.

    Declaration
    -
    public Guid RequestId { get; }
    +
    public Response Response { get; }
    Property Value
    @@ -249,21 +249,21 @@
    Property Value
    - +
    GuidResponse
    - -

    Response

    -

    Web Response.

    + +

    UpStreamEndPoint

    +

    Override UpStreamEndPoint for this request; Local NIC via request is made

    Declaration
    -
    public Response Response { get; }
    +
    public IPEndPoint UpStreamEndPoint { get; set; }
    Property Value
    @@ -275,21 +275,21 @@
    Property Value
    - +
    ResponseIPEndPoint
    - -

    UpStreamEndPoint

    -

    Override UpStreamEndPoint for this request; Local NIC via request is made

    + +

    UserData

    +

    Gets or sets the user data.

    Declaration
    -
    public IPEndPoint UpStreamEndPoint { get; set; }
    +
    public object UserData { get; set; }
    Property Value
    @@ -301,7 +301,7 @@
    Property Value
    - + diff --git a/docs/index.json b/docs/index.json index 00ac8e3c9..03cb941eb 100644 --- a/docs/index.json +++ b/docs/index.json @@ -32,17 +32,17 @@ "api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html": { "href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html", "title": "Class SessionEventArgs | Titanium Web Proxy", - "keywords": "Class SessionEventArgs Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferSize SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.Id SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class SessionEventArgs : SessionEventArgsBase, IDisposable Constructors SessionEventArgs(Int32, ProxyEndPoint, Request, CancellationTokenSource, ExceptionHandler) Declaration protected SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, Request request, CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc) Parameters Type Name Description Int32 bufferSize ProxyEndPoint endPoint Request request CancellationTokenSource cancellationTokenSource ExceptionHandler exceptionFunc Properties ReRequest Should we send the request again ? Declaration public bool ReRequest { get; set; } Property Value Type Description Boolean Methods Dispose() Implement any cleanup here Declaration public override void Dispose() Overrides SessionEventArgsBase.Dispose() GenericResponse(Byte[], HttpStatusCode, Dictionary) Before request is made to server respond with the specified byte[], the specified status to client. And then ignore the request. Declaration public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary headers) Parameters Type Name Description System.Byte [] result The bytes to sent. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. GenericResponse(String, HttpStatusCode, Dictionary) Before request is made to server respond with the specified HTML string and the specified status to client. And then ignore the request. Declaration public void GenericResponse(string html, HttpStatusCode status, Dictionary headers = null) Parameters Type Name Description String html The html content. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. GetRequestBody(CancellationToken) Gets the request body as bytes. Declaration public Task GetRequestBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < System.Byte []> The body as bytes. GetRequestBodyAsString(CancellationToken) Gets the request body as string. Declaration public Task GetRequestBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The body as string. GetResponseBody(CancellationToken) Gets the response body as bytes. Declaration public Task GetResponseBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < System.Byte []> The resulting bytes. GetResponseBodyAsString(CancellationToken) Gets the response body as string. Declaration public Task GetResponseBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The string body. Ok(Byte[], Dictionary) Before request is made to server respond with the specified byte[] to client and ignore the request. Declaration public void Ok(byte[] result, Dictionary headers = null) Parameters Type Name Description System.Byte [] result The html content bytes. Dictionary < String , HttpHeader > headers The HTTP headers. Ok(String, Dictionary) Before request is made to server respond with the specified HTML string to client and ignore the request. Declaration public void Ok(string html, Dictionary headers = null) Parameters Type Name Description String html HTML content to sent. Dictionary < String , HttpHeader > headers HTTP response headers. Redirect(String) Redirect to provided URL. Declaration public void Redirect(string url) Parameters Type Name Description String url The URL to redirect. Respond(Response) Respond with given response object to client. Declaration public void Respond(Response response) Parameters Type Name Description Response response The response object. SetRequestBody(Byte[]) Sets the request body. Declaration public void SetRequestBody(byte[] body) Parameters Type Name Description System.Byte [] body The request body bytes. SetRequestBodyString(String) Sets the body with the specified string. Declaration public void SetRequestBodyString(string body) Parameters Type Name Description String body The request body string to set. SetResponseBody(Byte[]) Set the response body bytes. Declaration public void SetResponseBody(byte[] body) Parameters Type Name Description System.Byte [] body The body bytes to set. SetResponseBodyString(String) Replace the response body with the specified string. Declaration public void SetResponseBodyString(string body) Parameters Type Name Description String body The body string to set. TerminateServerConnection() Terminate the connection to server. Declaration public void TerminateServerConnection() Events MultipartRequestPartSent Occurs when multipart request part sent. Declaration public event EventHandler MultipartRequestPartSent Event Type Type Description EventHandler < MultipartRequestPartSentEventArgs > Implements System.IDisposable" + "keywords": "Class SessionEventArgs Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferSize SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.UserData SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class SessionEventArgs : SessionEventArgsBase, IDisposable Constructors SessionEventArgs(Int32, ProxyEndPoint, Request, CancellationTokenSource, ExceptionHandler) Declaration protected SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, Request request, CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc) Parameters Type Name Description Int32 bufferSize ProxyEndPoint endPoint Request request CancellationTokenSource cancellationTokenSource ExceptionHandler exceptionFunc Properties ReRequest Should we send the request again ? Declaration public bool ReRequest { get; set; } Property Value Type Description Boolean Methods Dispose() Implement any cleanup here Declaration public override void Dispose() Overrides SessionEventArgsBase.Dispose() GenericResponse(Byte[], HttpStatusCode, Dictionary) Before request is made to server respond with the specified byte[], the specified status to client. And then ignore the request. Declaration public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary headers) Parameters Type Name Description System.Byte [] result The bytes to sent. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. GenericResponse(String, HttpStatusCode, Dictionary) Before request is made to server respond with the specified HTML string and the specified status to client. And then ignore the request. Declaration public void GenericResponse(string html, HttpStatusCode status, Dictionary headers = null) Parameters Type Name Description String html The html content. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. GetRequestBody(CancellationToken) Gets the request body as bytes. Declaration public Task GetRequestBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < System.Byte []> The body as bytes. GetRequestBodyAsString(CancellationToken) Gets the request body as string. Declaration public Task GetRequestBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The body as string. GetResponseBody(CancellationToken) Gets the response body as bytes. Declaration public Task GetResponseBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < System.Byte []> The resulting bytes. GetResponseBodyAsString(CancellationToken) Gets the response body as string. Declaration public Task GetResponseBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The string body. Ok(Byte[], Dictionary) Before request is made to server respond with the specified byte[] to client and ignore the request. Declaration public void Ok(byte[] result, Dictionary headers = null) Parameters Type Name Description System.Byte [] result The html content bytes. Dictionary < String , HttpHeader > headers The HTTP headers. Ok(String, Dictionary) Before request is made to server respond with the specified HTML string to client and ignore the request. Declaration public void Ok(string html, Dictionary headers = null) Parameters Type Name Description String html HTML content to sent. Dictionary < String , HttpHeader > headers HTTP response headers. Redirect(String) Redirect to provided URL. Declaration public void Redirect(string url) Parameters Type Name Description String url The URL to redirect. Respond(Response) Respond with given response object to client. Declaration public void Respond(Response response) Parameters Type Name Description Response response The response object. SetRequestBody(Byte[]) Sets the request body. Declaration public void SetRequestBody(byte[] body) Parameters Type Name Description System.Byte [] body The request body bytes. SetRequestBodyString(String) Sets the body with the specified string. Declaration public void SetRequestBodyString(string body) Parameters Type Name Description String body The request body string to set. SetResponseBody(Byte[]) Set the response body bytes. Declaration public void SetResponseBody(byte[] body) Parameters Type Name Description System.Byte [] body The body bytes to set. SetResponseBodyString(String) Replace the response body with the specified string. Declaration public void SetResponseBodyString(string body) Parameters Type Name Description String body The body string to set. TerminateServerConnection() Terminate the connection to server. Declaration public void TerminateServerConnection() Events MultipartRequestPartSent Occurs when multipart request part sent. Declaration public event EventHandler MultipartRequestPartSent Event Type Type Description EventHandler < MultipartRequestPartSentEventArgs > Implements System.IDisposable" }, "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html": { "href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html", "title": "Class SessionEventArgsBase | Titanium Web Proxy", - "keywords": "Class SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs TunnelConnectSessionEventArgs Implements IDisposable Inherited Members EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public abstract class SessionEventArgsBase : EventArgs, IDisposable Constructors SessionEventArgsBase(Int32, ProxyEndPoint, CancellationTokenSource, Request, ExceptionHandler) Declaration protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request, ExceptionHandler exceptionFunc) Parameters Type Name Description Int32 bufferSize ProxyEndPoint endPoint CancellationTokenSource cancellationTokenSource Request request ExceptionHandler exceptionFunc Fields BufferSize Size of Buffers used by this object Declaration protected readonly int BufferSize Field Value Type Description Int32 ExceptionFunc Declaration protected readonly ExceptionHandler ExceptionFunc Field Value Type Description ExceptionHandler Properties ClientEndPoint Client End Point. Declaration public IPEndPoint ClientEndPoint { get; } Property Value Type Description IPEndPoint CustomUpStreamProxyUsed Are we using a custom upstream HTTP(S) proxy? Declaration public ExternalProxy CustomUpStreamProxyUsed { get; } Property Value Type Description ExternalProxy Exception The last exception that happened. Declaration public Exception Exception { get; } Property Value Type Description Exception Id Returns a unique Id for this request/response session which is same as the RequestId of WebSession. Declaration public Guid Id { get; } Property Value Type Description Guid IsHttps Does this session uses SSL? Declaration public bool IsHttps { get; } Property Value Type Description Boolean IsTransparent Is this a transparent endpoint? Declaration public bool IsTransparent { get; } Property Value Type Description Boolean LocalEndPoint Local endpoint via which we make the request. Declaration public ProxyEndPoint LocalEndPoint { get; } Property Value Type Description ProxyEndPoint WebSession A web session corresponding to a single request/response sequence within a proxy connection. Declaration public HttpWebClient WebSession { get; } Property Value Type Description HttpWebClient Methods Dispose() Implements cleanup here. Declaration public virtual void Dispose() TerminateSession() Terminates the session abruptly by terminating client/server connections. Declaration public void TerminateSession() Events DataReceived Fired when data is received within this session from client/server. Declaration public event EventHandler DataReceived Event Type Type Description EventHandler < StreamExtended.Network.DataEventArgs > DataSent Fired when data is sent within this session to server/client. Declaration public event EventHandler DataSent Event Type Type Description EventHandler < StreamExtended.Network.DataEventArgs > Implements System.IDisposable" + "keywords": "Class SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs TunnelConnectSessionEventArgs Implements IDisposable Inherited Members EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public abstract class SessionEventArgsBase : EventArgs, IDisposable Constructors SessionEventArgsBase(Int32, ProxyEndPoint, CancellationTokenSource, Request, ExceptionHandler) Declaration protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request, ExceptionHandler exceptionFunc) Parameters Type Name Description Int32 bufferSize ProxyEndPoint endPoint CancellationTokenSource cancellationTokenSource Request request ExceptionHandler exceptionFunc Fields BufferSize Size of Buffers used by this object Declaration protected readonly int BufferSize Field Value Type Description Int32 ExceptionFunc Declaration protected readonly ExceptionHandler ExceptionFunc Field Value Type Description ExceptionHandler Properties ClientEndPoint Client End Point. Declaration public IPEndPoint ClientEndPoint { get; } Property Value Type Description IPEndPoint CustomUpStreamProxyUsed Are we using a custom upstream HTTP(S) proxy? Declaration public ExternalProxy CustomUpStreamProxyUsed { get; } Property Value Type Description ExternalProxy Exception The last exception that happened. Declaration public Exception Exception { get; } Property Value Type Description Exception IsHttps Does this session uses SSL? Declaration public bool IsHttps { get; } Property Value Type Description Boolean IsTransparent Is this a transparent endpoint? Declaration public bool IsTransparent { get; } Property Value Type Description Boolean LocalEndPoint Local endpoint via which we make the request. Declaration public ProxyEndPoint LocalEndPoint { get; } Property Value Type Description ProxyEndPoint UserData Returns a user data for this request/response session which is same as the user data of WebSession. Declaration public object UserData { get; set; } Property Value Type Description Object WebSession A web session corresponding to a single request/response sequence within a proxy connection. Declaration public HttpWebClient WebSession { get; } Property Value Type Description HttpWebClient Methods Dispose() Implements cleanup here. Declaration public virtual void Dispose() TerminateSession() Terminates the session abruptly by terminating client/server connections. Declaration public void TerminateSession() Events DataReceived Fired when data is received within this session from client/server. Declaration public event EventHandler DataReceived Event Type Type Description EventHandler < StreamExtended.Network.DataEventArgs > DataSent Fired when data is sent within this session to server/client. Declaration public event EventHandler DataSent Event Type Type Description EventHandler < StreamExtended.Network.DataEventArgs > Implements System.IDisposable" }, "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html": { "href": "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html", "title": "Class TunnelConnectSessionEventArgs | Titanium Web Proxy", - "keywords": "Class TunnelConnectSessionEventArgs A class that wraps the state when a tunnel connect event happen for Explicit endpoints. Inheritance Object EventArgs SessionEventArgsBase TunnelConnectSessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferSize SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.Id SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.Dispose() SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class TunnelConnectSessionEventArgs : SessionEventArgsBase, IDisposable Properties DecryptSsl Should we decrypt the Ssl or relay it to server? Default is true. Declaration public bool DecryptSsl { get; set; } Property Value Type Description Boolean DenyConnect When set to true it denies the connect request with a Forbidden status. Declaration public bool DenyConnect { get; set; } Property Value Type Description Boolean IsHttpsConnect Is this a connect request to secure HTTP server? Or is it to someother protocol. Declaration public bool IsHttpsConnect { get; } Property Value Type Description Boolean Implements System.IDisposable" + "keywords": "Class TunnelConnectSessionEventArgs A class that wraps the state when a tunnel connect event happen for Explicit endpoints. Inheritance Object EventArgs SessionEventArgsBase TunnelConnectSessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferSize SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.UserData SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.Dispose() SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class TunnelConnectSessionEventArgs : SessionEventArgsBase, IDisposable Properties DecryptSsl Should we decrypt the Ssl or relay it to server? Default is true. Declaration public bool DecryptSsl { get; set; } Property Value Type Description Boolean DenyConnect When set to true it denies the connect request with a Forbidden status. Declaration public bool DenyConnect { get; set; } Property Value Type Description Boolean IsHttpsConnect Is this a connect request to secure HTTP server? Or is it to someother protocol. Declaration public bool IsHttpsConnect { get; } Property Value Type Description Boolean Implements System.IDisposable" }, "api/Titanium.Web.Proxy.ExceptionHandler.html": { "href": "api/Titanium.Web.Proxy.ExceptionHandler.html", @@ -102,7 +102,7 @@ "api/Titanium.Web.Proxy.Http.HttpWebClient.html": { "href": "api/Titanium.Web.Proxy.Http.HttpWebClient.html", "title": "Class HttpWebClient | Titanium Web Proxy", - "keywords": "Class HttpWebClient Used to communicate with the server over HTTP(S) Inheritance Object HttpWebClient Inherited Members Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Http Assembly : Titanium.Web.Proxy.dll Syntax public class HttpWebClient Properties ConnectRequest Headers passed with Connect. Declaration public ConnectRequest ConnectRequest { get; } Property Value Type Description ConnectRequest IsHttps Is Https? Declaration public bool IsHttps { get; } Property Value Type Description Boolean ProcessId PID of the process that is created the current session when client is running in this machine If client is remote then this will return Declaration public Lazy ProcessId { get; } Property Value Type Description Lazy < Int32 > Request Web Request. Declaration public Request Request { get; } Property Value Type Description Request RequestId Request ID. Declaration public Guid RequestId { get; } Property Value Type Description Guid Response Web Response. Declaration public Response Response { get; } Property Value Type Description Response UpStreamEndPoint Override UpStreamEndPoint for this request; Local NIC via request is made Declaration public IPEndPoint UpStreamEndPoint { get; set; } Property Value Type Description IPEndPoint" + "keywords": "Class HttpWebClient Used to communicate with the server over HTTP(S) Inheritance Object HttpWebClient Inherited Members Object.ToString() Object.Equals(Object) Object.Equals(Object, Object) Object.ReferenceEquals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Namespace : Titanium.Web.Proxy.Http Assembly : Titanium.Web.Proxy.dll Syntax public class HttpWebClient Properties ConnectRequest Headers passed with Connect. Declaration public ConnectRequest ConnectRequest { get; } Property Value Type Description ConnectRequest IsHttps Is Https? Declaration public bool IsHttps { get; } Property Value Type Description Boolean ProcessId PID of the process that is created the current session when client is running in this machine If client is remote then this will return Declaration public Lazy ProcessId { get; } Property Value Type Description Lazy < Int32 > Request Web Request. Declaration public Request Request { get; } Property Value Type Description Request Response Web Response. Declaration public Response Response { get; } Property Value Type Description Response UpStreamEndPoint Override UpStreamEndPoint for this request; Local NIC via request is made Declaration public IPEndPoint UpStreamEndPoint { get; set; } Property Value Type Description IPEndPoint UserData Gets or sets the user data. Declaration public object UserData { get; set; } Property Value Type Description Object" }, "api/Titanium.Web.Proxy.Http.KnownHeaders.html": { "href": "api/Titanium.Web.Proxy.Http.KnownHeaders.html", diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index b3ffa94f8..33d47e847 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -586,19 +586,6 @@ references: commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc nameWithType: SessionEventArgsBase.ExceptionFunc -- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Id - name: Id - href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Id - commentId: P:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Id - fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Id - nameWithType: SessionEventArgsBase.Id -- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Id* - name: Id - href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Id_ - commentId: Overload:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Id - isSpec: "True" - fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Id - nameWithType: SessionEventArgsBase.Id - uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps name: IsHttps href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps @@ -651,6 +638,19 @@ references: isSpec: "True" fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession nameWithType: SessionEventArgsBase.TerminateSession +- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData + name: UserData + href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData + commentId: P:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData + fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData + nameWithType: SessionEventArgsBase.UserData +- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData* + name: UserData + href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData_ + commentId: Overload:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData + isSpec: "True" + fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData + nameWithType: SessionEventArgsBase.UserData - uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession name: WebSession href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession @@ -1130,19 +1130,6 @@ references: isSpec: "True" fullName: Titanium.Web.Proxy.Http.HttpWebClient.Request nameWithType: HttpWebClient.Request -- uid: Titanium.Web.Proxy.Http.HttpWebClient.RequestId - name: RequestId - href: api/Titanium.Web.Proxy.Http.HttpWebClient.html#Titanium_Web_Proxy_Http_HttpWebClient_RequestId - commentId: P:Titanium.Web.Proxy.Http.HttpWebClient.RequestId - fullName: Titanium.Web.Proxy.Http.HttpWebClient.RequestId - nameWithType: HttpWebClient.RequestId -- uid: Titanium.Web.Proxy.Http.HttpWebClient.RequestId* - name: RequestId - href: api/Titanium.Web.Proxy.Http.HttpWebClient.html#Titanium_Web_Proxy_Http_HttpWebClient_RequestId_ - commentId: Overload:Titanium.Web.Proxy.Http.HttpWebClient.RequestId - isSpec: "True" - fullName: Titanium.Web.Proxy.Http.HttpWebClient.RequestId - nameWithType: HttpWebClient.RequestId - uid: Titanium.Web.Proxy.Http.HttpWebClient.Response name: Response href: api/Titanium.Web.Proxy.Http.HttpWebClient.html#Titanium_Web_Proxy_Http_HttpWebClient_Response @@ -1169,6 +1156,19 @@ references: isSpec: "True" fullName: Titanium.Web.Proxy.Http.HttpWebClient.UpStreamEndPoint nameWithType: HttpWebClient.UpStreamEndPoint +- uid: Titanium.Web.Proxy.Http.HttpWebClient.UserData + name: UserData + href: api/Titanium.Web.Proxy.Http.HttpWebClient.html#Titanium_Web_Proxy_Http_HttpWebClient_UserData + commentId: P:Titanium.Web.Proxy.Http.HttpWebClient.UserData + fullName: Titanium.Web.Proxy.Http.HttpWebClient.UserData + nameWithType: HttpWebClient.UserData +- uid: Titanium.Web.Proxy.Http.HttpWebClient.UserData* + name: UserData + href: api/Titanium.Web.Proxy.Http.HttpWebClient.html#Titanium_Web_Proxy_Http_HttpWebClient_UserData_ + commentId: Overload:Titanium.Web.Proxy.Http.HttpWebClient.UserData + isSpec: "True" + fullName: Titanium.Web.Proxy.Http.HttpWebClient.UserData + nameWithType: HttpWebClient.UserData - uid: Titanium.Web.Proxy.Http.KnownHeaders name: KnownHeaders href: api/Titanium.Web.Proxy.Http.KnownHeaders.html From ca08a33d534e75ff359298b0edc961dc3bed2248 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Sun, 6 May 2018 09:00:20 -0400 Subject: [PATCH 18/23] update example without RequestId --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 807816c32..26a345423 100644 --- a/README.md +++ b/README.md @@ -122,8 +122,8 @@ Sample request and response event handlers ```csharp //To access requestBody from OnResponse handler -private IDictionary requestBodyHistory - = new ConcurrentDictionary(); +private HashSet requestHistory + = new HashSet(); private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { @@ -156,9 +156,10 @@ public async Task OnRequest(object sender, SessionEventArgs e) string bodyString = await e.GetRequestBodyAsString(); await e.SetRequestBodyString(bodyString); - //store request Body/request headers etc with request Id as key + //store request //so that you can find it from response handler using request Id - requestBodyHistory[e.Id] = bodyString; + //You can also use e.UserData to set any user data and access it from response + requestHistory.Add(e); } //To cancel a request with a custom HTML content @@ -202,10 +203,10 @@ public async Task OnResponse(object sender, SessionEventArgs e) } } - //access request body/request headers etc by looking up using requestId - if(requestBodyHistory.ContainsKey(e.Id)) + //access request by looking up HashSet + if(requestHistory.ContainsKey(e)) { - var requestBody = requestBodyHistory[e.Id]; + var request = requestHistory[e]; } } From 8818a9e237a9cbc74fe40201a1093eb4994d0706 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Sun, 6 May 2018 09:06:51 -0400 Subject: [PATCH 19/23] update example --- README.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 26a345423..f3756eed6 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,6 @@ Sample request and response event handlers ```csharp -//To access requestBody from OnResponse handler -private HashSet requestHistory - = new HashSet(); - private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) { string hostname = e.WebSession.Request.RequestUri.Host; @@ -157,9 +153,8 @@ public async Task OnRequest(object sender, SessionEventArgs e) await e.SetRequestBodyString(bodyString); //store request - //so that you can find it from response handler using request Id - //You can also use e.UserData to set any user data and access it from response - requestHistory.Add(e); + //so that you can find it from response handler + e.UserData = e.WebSession.Request; } //To cancel a request with a custom HTML content @@ -203,11 +198,9 @@ public async Task OnResponse(object sender, SessionEventArgs e) } } - //access request by looking up HashSet - if(requestHistory.ContainsKey(e)) - { - var request = requestHistory[e]; - } + //access request from UserData property where we stored it in RequestHandler + var request = (Request)e.UserData; + } /// Allows overriding default certificate validation logic From b06dd785dbc8897b807a735db2a0829ed82d1369 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Sun, 6 May 2018 09:07:50 -0400 Subject: [PATCH 20/23] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f3756eed6..ee05f9366 100644 --- a/README.md +++ b/README.md @@ -198,8 +198,11 @@ public async Task OnResponse(object sender, SessionEventArgs e) } } - //access request from UserData property where we stored it in RequestHandler - var request = (Request)e.UserData; + if(e.UserData!=null) + { + //access request from UserData property where we stored it in RequestHandler + var request = (Request)e.UserData; + } } From a013e3119dbe3ac7fe6b7b64996b9eddf32a8005 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Sun, 6 May 2018 16:27:26 -0400 Subject: [PATCH 21/23] #428 Fix incorrect compression relay --- .../ProxyTestController.cs | 61 +++++++------------ Titanium.Web.Proxy/RequestHandler.cs | 28 +++++++-- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs index 348fb8adb..acb4b791d 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs +++ b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs @@ -18,21 +18,8 @@ public class ProxyTestController private readonly ProxyServer proxyServer; - // keep track of request headers - private readonly IDictionary requestHeaderHistory = - new ConcurrentDictionary(); - - // keep track of response headers - private readonly IDictionary responseHeaderHistory = - new ConcurrentDictionary(); - private ExplicitProxyEndPoint explicitEndPoint; - // share requestBody outside handlers - // Using a dictionary is not a good idea since it can cause memory overflow - // ideally the data should be moved out of memory - // private readonly IDictionary requestBodyHistory = new ConcurrentDictionary(); - public ProxyTestController() { proxyServer = new ProxyServer(); @@ -164,12 +151,14 @@ private async Task OnRequest(object sender, SessionEventArgs e) WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount); WriteToConsole(e.WebSession.Request.Url); - // create custom id for the request and store it in the UserData property + // store it in the UserData property // It can be a simple integer, Guid, or any type - e.UserData = Guid.NewGuid(); - - // read request headers - requestHeaderHistory[(Guid)e.UserData] = e.WebSession.Request.Headers; + //e.UserData = new CustomUserData() + //{ + // RequestHeaders = e.WebSession.Request.Headers, + // RequestBody = e.WebSession.Request.HasBody ? e.WebSession.Request.Body:null, + // RequestBodyString = e.WebSession.Request.HasBody? e.WebSession.Request.BodyString:null + //}; ////This sample shows how to get the multipart form data headers //if (e.WebSession.Request.Host == "mail.yahoo.com" && e.WebSession.Request.IsMultipartFormData) @@ -177,19 +166,6 @@ private async Task OnRequest(object sender, SessionEventArgs e) // e.MultipartRequestPartSent += MultipartRequestPartSent; //} - //if (e.WebSession.Request.HasBody) - //{ - // // Get/Set request body bytes - // var bodyBytes = await e.GetRequestBody(); - // await e.SetRequestBody(bodyBytes); - - // // Get/Set request body as string - // string bodyString = await e.GetRequestBodyAsString(); - // await e.SetRequestBodyString(bodyString); - - // //requestBodyHistory[e.Id] = bodyString; - //} - // To cancel a request with a custom HTML content // Filter URL //if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("yahoo.com")) @@ -227,6 +203,9 @@ private async Task OnResponse(object sender, SessionEventArgs e) string ext = System.IO.Path.GetExtension(e.WebSession.Request.RequestUri.AbsolutePath); + //access user data set in request to do something with it + //var userData = e.WebSession.UserData as CustomUserData; + //if (ext == ".gif" || ext == ".png" || ext == ".jpg") //{ // byte[] btBody = Encoding.UTF8.GetBytes("" + @@ -243,15 +222,6 @@ private async Task OnResponse(object sender, SessionEventArgs e) // e.Respond(response); // e.TerminateServerConnection(); //} - - //if (requestBodyHistory.ContainsKey(e.Id)) - //{ - // // access request body by looking up the shared dictionary using requestId - // var requestBody = requestBodyHistory[e.Id]; - //} - - ////read response headers - //responseHeaderHistory[e.Id] = e.WebSession.Response.Headers; //// print out process id of current session ////WriteToConsole($"PID: {e.WebSession.ProcessId.Value}"); @@ -308,5 +278,16 @@ private void WriteToConsole(string message) Console.WriteLine(message); } } + + ///// + ///// User data object as defined by user. + ///// User data can be set to each SessionEventArgs.WebSession.UserData property + ///// + //public class CustomUserData + //{ + // public HeaderCollection RequestHeaders { get; set; } + // public byte[] RequestBody { get; set; } + // public string RequestBodyString { get; set; } + //} } } diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index e74e6c7a4..a1d067633 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net; -using System.Net.Security; +using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -24,9 +25,15 @@ public partial class ProxyServer private static readonly Regex uriSchemeRegex = new Regex("^[a-z]*://", RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static readonly HashSet proxySupportedCompressions = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "gzip", + "deflate" + }; + private bool isWindowsAuthenticationEnabledAndSupported => EnableWinAuth && RunTime.IsWindows && !RunTime.IsRunningOnMono; - + /// /// This is the core request handler method for a particular connection from client. /// Will create new session (request/response) sequence until @@ -404,12 +411,23 @@ private async Task GetServerConnection(SessionEventArgsBase /// /// Prepare the request headers so that we can avoid encodings not parsable by this proxy /// - /// private void PrepareRequestHeaders(HeaderCollection requestHeaders) { - if (requestHeaders.HeaderExists(KnownHeaders.AcceptEncoding)) + var acceptEncoding = requestHeaders.GetHeaderValueOrNull(KnownHeaders.AcceptEncoding); + + if (acceptEncoding != null) { - requestHeaders.SetOrAddHeaderValue(KnownHeaders.AcceptEncoding, "gzip,deflate"); + var supporedAcceptEncoding = new List(); + + //only allow proxy supported compressions + supporedAcceptEncoding.AddRange(acceptEncoding.Split(',') + .Select(x => x.Trim()) + .Where(x => proxySupportedCompressions.Contains(x))); + + //uncompressed is always supported by proxy + supporedAcceptEncoding.Add("identity"); + + requestHeaders.SetOrAddHeaderValue(KnownHeaders.AcceptEncoding, string.Join(",", supporedAcceptEncoding)); } requestHeaders.FixProxyHeaders(); From 76d99c84d333e3c6462c14090a00bbbd06fd15b3 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Sun, 6 May 2018 16:28:36 -0400 Subject: [PATCH 22/23] spelling --- Titanium.Web.Proxy/RequestHandler.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs index a1d067633..828e1451d 100644 --- a/Titanium.Web.Proxy/RequestHandler.cs +++ b/Titanium.Web.Proxy/RequestHandler.cs @@ -417,17 +417,17 @@ private void PrepareRequestHeaders(HeaderCollection requestHeaders) if (acceptEncoding != null) { - var supporedAcceptEncoding = new List(); + var supportedAcceptEncoding = new List(); //only allow proxy supported compressions - supporedAcceptEncoding.AddRange(acceptEncoding.Split(',') + supportedAcceptEncoding.AddRange(acceptEncoding.Split(',') .Select(x => x.Trim()) .Where(x => proxySupportedCompressions.Contains(x))); //uncompressed is always supported by proxy - supporedAcceptEncoding.Add("identity"); + supportedAcceptEncoding.Add("identity"); - requestHeaders.SetOrAddHeaderValue(KnownHeaders.AcceptEncoding, string.Join(",", supporedAcceptEncoding)); + requestHeaders.SetOrAddHeaderValue(KnownHeaders.AcceptEncoding, string.Join(",", supportedAcceptEncoding)); } requestHeaders.FixProxyHeaders(); From ad5a5d3cb79968fa64eafee9d025b54d84b93b68 Mon Sep 17 00:00:00 2001 From: justcoding121 Date: Mon, 7 May 2018 10:08:46 -0400 Subject: [PATCH 23/23] Update streamextended package --- .../Titanium.Web.Proxy.Examples.Wpf.csproj | 4 ++-- Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config | 3 +-- Titanium.Web.Proxy/Titanium.Web.Proxy.csproj | 2 +- Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec | 2 +- Titanium.Web.Proxy/packages.config | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) 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 0e6284a64..d6b34be73 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 @@ -51,8 +51,8 @@ 4 - - ..\..\packages\StreamExtended.1.0.160-beta\lib\net45\StreamExtended.dll + + ..\..\packages\StreamExtended.1.0.164\lib\net45\StreamExtended.dll diff --git a/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config b/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config index 89e1575a6..d9e9bf93f 100644 --- a/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config +++ b/Examples/Titanium.Web.Proxy.Examples.Wpf/packages.config @@ -1,5 +1,4 @@  - - + \ No newline at end of file diff --git a/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj b/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj index 051979fd6..070b82d5b 100644 --- a/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj +++ b/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj @@ -13,7 +13,7 @@ - + diff --git a/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec b/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec index 7a6d4ced2..5e9951f7b 100644 --- a/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec +++ b/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec @@ -14,7 +14,7 @@ Copyright © Titanium. All rights reserved. - + diff --git a/Titanium.Web.Proxy/packages.config b/Titanium.Web.Proxy/packages.config index 2a2a3a11a..6e9fe7e97 100644 --- a/Titanium.Web.Proxy/packages.config +++ b/Titanium.Web.Proxy/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file
    IPEndPointObject