From 8efd05c3a45eec155dca02b6038fd6d89e8042d8 Mon Sep 17 00:00:00 2001
From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com>
Date: Thu, 6 Jun 2024 20:12:02 +0000
Subject: [PATCH 1/4] Dev container config
---
.devcontainer/devcontainer.json | 37 +++++++++++++++++++
.github/dependabot.yml | 12 ++++++
.../Titanium.Web.Proxy.csproj | 2 +-
3 files changed, 50 insertions(+), 1 deletion(-)
create mode 100644 .devcontainer/devcontainer.json
create mode 100644 .github/dependabot.yml
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 00000000..bd4f19ef
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,37 @@
+// For format details, see https://aka.ms/devcontainer.json. For config options, see the
+// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
+{
+ "name": "C# (.NET)",
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
+ "image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm",
+ "features": {
+ "ghcr.io/devcontainers/features/dotnet:2": {}
+ },
+
+ // Features to add to the dev container. More info: https://containers.dev/features.
+ // "features": {},
+
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
+ // "forwardPorts": [5000, 5001],
+ // "portsAttributes": {
+ // "5001": {
+ // "protocol": "https"
+ // }
+ // }
+
+ // Use 'postCreateCommand' to run commands after the container is created.
+ // "postCreateCommand": "dotnet restore",
+
+ // Configure tool-specific properties.
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-dotnettools.csdevkit",
+ "GitHub.copilot-chat"
+ ]
+ }
+ }
+
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
+ // "remoteUser": "root"
+}
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..f33a02cd
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for more information:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+# https://containers.dev/guide/dependabot
+
+version: 2
+updates:
+ - package-ecosystem: "devcontainers"
+ directory: "/"
+ schedule:
+ interval: weekly
diff --git a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
index 797580af..7a05bce3 100644
--- a/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+++ b/src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
@@ -24,7 +24,7 @@
1701;1702;CA1416
- 1701;1702;CA1416;CS1591
+ 1701;1702;CA1416
From b0bd107c22cb81f9631189cd2ac3d63af4ae06a8 Mon Sep 17 00:00:00 2001
From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com>
Date: Thu, 6 Jun 2024 20:17:34 +0000
Subject: [PATCH 2/4] chore: Enable Windows targetting to be able to restore on
ubuntu
---
.../Titanium.Web.Proxy.Examples.Basic.csproj | 1 +
.../Titanium.Web.Proxy.Examples.WindowsService.csproj | 2 ++
.../Titanium.Web.Proxy.Examples.Wpf.csproj | 1 +
3 files changed, 4 insertions(+)
diff --git a/examples/Titanium.Web.Proxy.Examples.Basic/Titanium.Web.Proxy.Examples.Basic.csproj b/examples/Titanium.Web.Proxy.Examples.Basic/Titanium.Web.Proxy.Examples.Basic.csproj
index 7924f94c..ae88bbab 100644
--- a/examples/Titanium.Web.Proxy.Examples.Basic/Titanium.Web.Proxy.Examples.Basic.csproj
+++ b/examples/Titanium.Web.Proxy.Examples.Basic/Titanium.Web.Proxy.Examples.Basic.csproj
@@ -2,6 +2,7 @@
Exe
net8.0
+ true
diff --git a/examples/Titanium.Web.Proxy.Examples.WindowsService/Titanium.Web.Proxy.Examples.WindowsService.csproj b/examples/Titanium.Web.Proxy.Examples.WindowsService/Titanium.Web.Proxy.Examples.WindowsService.csproj
index d9379025..e9d4c9ba 100644
--- a/examples/Titanium.Web.Proxy.Examples.WindowsService/Titanium.Web.Proxy.Examples.WindowsService.csproj
+++ b/examples/Titanium.Web.Proxy.Examples.WindowsService/Titanium.Web.Proxy.Examples.WindowsService.csproj
@@ -19,6 +19,8 @@
0
1.0.0.%2a
false
+
+ true
win-x64
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 e9dbc810..57fc7df7 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
@@ -3,6 +3,7 @@
WinExe
net8.0-windows
true
+ true
From 613e25a198f3dbf75f80668c9faf0b90a0d8af50 Mon Sep 17 00:00:00 2001
From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com>
Date: Thu, 6 Jun 2024 20:52:21 +0000
Subject: [PATCH 3/4] Docs: Document undocumented methods
---
.../Certificates/CertificateManager.cs | 6 ++
.../EventArguments/SessionEventArgs.cs | 8 ++
.../EventArguments/TunnelConnectEventArgs.cs | 3 +
src/Titanium.Web.Proxy/Helpers/RunTime.cs | 16 ++-
.../Http/HeaderCollection.cs | 3 +
src/Titanium.Web.Proxy/Http/KnownHeaders.cs | 100 +++++++++++++++++-
.../Http/RequestResponseBase.cs | 3 +
src/Titanium.Web.Proxy/Http/TunnelType.cs | 20 +++-
.../Http2/Hpack/DynamicTable.cs | 3 +
.../Http2/Hpack/HuffmanDecoder.cs | 9 +-
.../Models/ExternalProxy.cs | 9 ++
src/Titanium.Web.Proxy/Models/HttpHeader.cs | 6 ++
.../Models/IExternalProxy.cs | 26 +++--
.../Models/ProxyAuthenticationContext.cs | 23 ++--
.../Models/ProxyProtocolType.cs | 7 +-
.../Models/TransparentBaseProxyEndPoint.cs | 11 ++
.../Network/BufferPool/IBufferPool.cs | 20 +++-
.../Network/Readers/IHttpStreamReader.cs | 30 ++++++
.../Network/Streams/ILineStream.cs | 23 +++-
.../Network/Streams/IPeekStream.cs | 35 +++---
.../Network/Writers/IHttpStreamWriter.cs | 32 +++++-
src/Titanium.Web.Proxy/ProxyServer.cs | 5 +
.../WebSocket/WebSocketDecoder.cs | 13 ++-
.../WebSocket/WebSocketFrame.cs | 23 ++++
.../WebSocket/WebsocketOpCode.cs | 27 +++++
25 files changed, 417 insertions(+), 44 deletions(-)
diff --git a/src/Titanium.Web.Proxy/Certificates/CertificateManager.cs b/src/Titanium.Web.Proxy/Certificates/CertificateManager.cs
index 7769c7c0..f3dacfcf 100644
--- a/src/Titanium.Web.Proxy/Certificates/CertificateManager.cs
+++ b/src/Titanium.Web.Proxy/Certificates/CertificateManager.cs
@@ -24,6 +24,10 @@ public enum CertificateEngine
///
BouncyCastle = 0,
+ ///
+ /// Uses BouncyCastle 3rd party library.
+ /// Observed to be faster than BouncyCastle.
+ ///
BouncyCastleFast = 2,
///
@@ -279,6 +283,7 @@ public ICertificateCache CertificateStorage
///
public bool DisableWildCardCertificates { get; set; } = false;
+ ///
public void Dispose()
{
Dispose(true);
@@ -951,6 +956,7 @@ private void Dispose(bool disposing)
disposed = true;
}
+ ///
~CertificateManager()
{
Dispose(false);
diff --git a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
index 682e534c..0e87a365 100644
--- a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+++ b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
@@ -60,8 +60,14 @@ public bool ReRequest
}
}
+ ///
+ /// WebSocket decoder for sending data to server
+ ///
public WebSocketDecoder WebSocketDecoderSend => webSocketDecoderSend ??= new WebSocketDecoder(BufferPool);
+ ///
+ /// WebSocket decoder for receiving data from server
+ ///
public WebSocketDecoder WebSocketDecoderReceive => webSocketDecoderReceive ??= new WebSocketDecoder(BufferPool);
///
@@ -611,6 +617,7 @@ public void TerminateServerConnection()
HttpClient.CloseServerConnection = true;
}
+ ///
protected override void Dispose(bool disposing)
{
if (disposed) return;
@@ -621,6 +628,7 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}
+ ///
~SessionEventArgs()
{
#if DEBUG
diff --git a/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
index b9b74989..7f3d73d3 100644
--- a/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
+++ b/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
@@ -76,6 +76,9 @@ internal void OnDecryptedDataReceived(byte[] buffer, int offset, int count)
}
}
+ ///
+ /// Dispose the object.
+ ///
~TunnelConnectSessionEventArgs()
{
#if DEBUG
diff --git a/src/Titanium.Web.Proxy/Helpers/RunTime.cs b/src/Titanium.Web.Proxy/Helpers/RunTime.cs
index b528ff2c..30486acd 100644
--- a/src/Titanium.Web.Proxy/Helpers/RunTime.cs
+++ b/src/Titanium.Web.Proxy/Helpers/RunTime.cs
@@ -52,16 +52,30 @@ public static class RunTime
#endif
///
- /// Is running on Mono?
+ /// Is running on Mono?
///
internal static bool IsRunningOnMono => isRunningOnMono.Value;
+ ///
+ /// Is running on Linux?
+ ///
public static bool IsLinux => IsRunningOnLinux;
+ ///
+ /// Is running on Windows?
+ ///
+ /// Don't forget to also check
public static bool IsWindows => IsRunningOnWindows;
+ ///
+ /// Is running on UWP on Windows?
+ ///
+ /// Don't forget to also check
public static bool IsUwpOnWindows => IsWindows && UwpHelper.IsRunningAsUwp();
+ ///
+ /// Is running on Mac?
+ ///
public static bool IsMac => IsRunningOnMac;
private static bool? _isSocketReuseAvailable;
diff --git a/src/Titanium.Web.Proxy/Http/HeaderCollection.cs b/src/Titanium.Web.Proxy/Http/HeaderCollection.cs
index a314023e..c3e9d6a1 100644
--- a/src/Titanium.Web.Proxy/Http/HeaderCollection.cs
+++ b/src/Titanium.Web.Proxy/Http/HeaderCollection.cs
@@ -84,6 +84,9 @@ public bool HeaderExists(string name)
return null;
}
+ ///
+ /// Gets the first header with given name if exists
+ ///
public HttpHeader? GetFirstHeader(string name)
{
if (headers.TryGetValue(name, out var header)) return header;
diff --git a/src/Titanium.Web.Proxy/Http/KnownHeaders.cs b/src/Titanium.Web.Proxy/Http/KnownHeaders.cs
index 3c385e5a..8e6a9578 100644
--- a/src/Titanium.Web.Proxy/Http/KnownHeaders.cs
+++ b/src/Titanium.Web.Proxy/Http/KnownHeaders.cs
@@ -1,51 +1,143 @@
namespace Titanium.Web.Proxy.Http;
///
-/// Well known http headers.
+/// The KnownHeaders class provides static instances of known HTTP headers.
+/// These instances can be used to avoid the overhead of creating new strings for common headers.
///
public static class KnownHeaders
{
- // Both
+ ///
+ /// The 'Connection' HTTP header.
+ ///
public static KnownHeader Connection = "Connection";
+
+ ///
+ /// The 'close' value for the 'Connection' HTTP header.
+ ///
public static KnownHeader ConnectionClose = "close";
+
+ ///
+ /// The 'keep-alive' value for the 'Connection' HTTP header.
+ ///
public static KnownHeader ConnectionKeepAlive = "keep-alive";
+ ///
+ /// The 'Content-Length' HTTP header.
+ ///
public static KnownHeader ContentLength = "Content-Length";
+
+ ///
+ /// The 'content-length' HTTP header for HTTP/2.
+ ///
public static KnownHeader ContentLengthHttp2 = "content-length";
+ ///
+ /// The 'Content-Type' HTTP header.
+ ///
public static KnownHeader ContentType = "Content-Type";
+
+ ///
+ /// The 'charset' value for the 'Content-Type' HTTP header.
+ ///
public static KnownHeader ContentTypeCharset = "charset";
+
+ ///
+ /// The 'boundary' value for the 'Content-Type' HTTP header.
+ ///
public static KnownHeader ContentTypeBoundary = "boundary";
+ ///
+ /// The 'Upgrade' HTTP header.
+ ///
public static KnownHeader Upgrade = "Upgrade";
+
+ ///
+ /// The 'websocket' value for the 'Upgrade' HTTP header.
+ ///
public static KnownHeader UpgradeWebsocket = "websocket";
- // Request headers
+ ///
+ /// The 'Accept-Encoding' HTTP header.
+ ///
public static KnownHeader AcceptEncoding = "Accept-Encoding";
+ ///
+ /// The 'Authorization' HTTP header.
+ ///
public static KnownHeader Authorization = "Authorization";
+ ///
+ /// The 'Expect' HTTP header.
+ ///
public static KnownHeader Expect = "Expect";
+
+ ///
+ /// The '100-continue' expectation for the 'Expect' HTTP header.
+ ///
public static KnownHeader Expect100Continue = "100-continue";
+ ///
+ /// The 'Host' HTTP header.
+ ///
public static KnownHeader Host = "Host";
+ ///
+ /// The 'Proxy-Authorization' HTTP header.
+ ///
public static KnownHeader ProxyAuthorization = "Proxy-Authorization";
+
+ ///
+ /// The 'basic' value for the 'Proxy-Authorization' HTTP header.
+ ///
public static KnownHeader ProxyAuthorizationBasic = "basic";
+ ///
+ /// The 'Proxy-Connection' HTTP header.
+ ///
public static KnownHeader ProxyConnection = "Proxy-Connection";
+
+ ///
+ /// The 'close' value for the 'Proxy-Connection' HTTP header.
+ ///
public static KnownHeader ProxyConnectionClose = "close";
- // Response headers
+ ///
+ /// The 'Content-Encoding' HTTP header.
+ ///
public static KnownHeader ContentEncoding = "Content-Encoding";
+
+ ///
+ /// The 'deflate' value for the 'Content-Encoding' HTTP header.
+ ///
public static KnownHeader ContentEncodingDeflate = "deflate";
+
+ ///
+ /// The 'gzip' value for the 'Content-Encoding' HTTP header.
+ ///
public static KnownHeader ContentEncodingGzip = "gzip";
+
+ ///
+ /// The 'br' (Brotli) value for the 'Content-Encoding' HTTP header.
+ ///
public static KnownHeader ContentEncodingBrotli = "br";
+ ///
+ /// The 'Location' HTTP header.
+ ///
public static KnownHeader Location = "Location";
+ ///
+ /// The 'Proxy-Authenticate' HTTP header.
+ ///
public static KnownHeader ProxyAuthenticate = "Proxy-Authenticate";
+ ///
+ /// The 'Transfer-Encoding' HTTP header.
+ ///
public static KnownHeader TransferEncoding = "Transfer-Encoding";
+
+ ///
+ /// The 'chunked' value for the 'Transfer-Encoding' HTTP header.
+ ///
public static KnownHeader TransferEncodingChunked = "chunked";
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs b/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs
index 4b785abb..46aad491 100644
--- a/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs
+++ b/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs
@@ -300,6 +300,9 @@ internal void FinishSession()
}
}
+ ///
+ /// HeaderText as string
+ ///
public override string ToString()
{
return HeaderText;
diff --git a/src/Titanium.Web.Proxy/Http/TunnelType.cs b/src/Titanium.Web.Proxy/Http/TunnelType.cs
index c000a0bd..914ba82f 100644
--- a/src/Titanium.Web.Proxy/Http/TunnelType.cs
+++ b/src/Titanium.Web.Proxy/Http/TunnelType.cs
@@ -1,9 +1,27 @@
namespace Titanium.Web.Proxy.Http;
+///
+/// The TunnelType enumeration represents the type of tunnel used in a proxy connection.
+///
public enum TunnelType
{
+ ///
+ /// The tunnel type is unknown.
+ ///
Unknown,
+
+ ///
+ /// The tunnel is used for HTTPS connections.
+ ///
Https,
+
+ ///
+ /// The tunnel is used for WebSocket connections.
+ ///
Websocket,
+
+ ///
+ /// The tunnel is used for HTTP/2 connections.
+ ///
Http2
-}
\ No newline at end of file
+}
diff --git a/src/Titanium.Web.Proxy/Http2/Hpack/DynamicTable.cs b/src/Titanium.Web.Proxy/Http2/Hpack/DynamicTable.cs
index 7c9c94dc..6779e3d1 100644
--- a/src/Titanium.Web.Proxy/Http2/Hpack/DynamicTable.cs
+++ b/src/Titanium.Web.Proxy/Http2/Hpack/DynamicTable.cs
@@ -20,6 +20,9 @@
namespace Titanium.Web.Proxy.Http2.Hpack;
+///
+/// A dynamic table of header fields.
+///
public class DynamicTable
{
// a circular queue of header fields
diff --git a/src/Titanium.Web.Proxy/Http2/Hpack/HuffmanDecoder.cs b/src/Titanium.Web.Proxy/Http2/Hpack/HuffmanDecoder.cs
index 3a0566b3..959293b5 100644
--- a/src/Titanium.Web.Proxy/Http2/Hpack/HuffmanDecoder.cs
+++ b/src/Titanium.Web.Proxy/Http2/Hpack/HuffmanDecoder.cs
@@ -19,7 +19,14 @@
using System.IO;
namespace Titanium.Web.Proxy.Http2.Hpack;
-
+///
+/// The HuffmanDecoder class is responsible for decoding Huffman encoded data.
+/// It uses a Huffman tree built from predefined Huffman codes and lengths.
+/// The decoding process involves traversing the Huffman tree based on the input data,
+/// and outputting the symbol when a terminal node is reached.
+/// This class is designed to be used in the context of HPACK (Header Compression for HTTP/2),
+/// where Huffman coding is used to compress HTTP headers.
+///
public class HuffmanDecoder
{
///
diff --git a/src/Titanium.Web.Proxy/Models/ExternalProxy.cs b/src/Titanium.Web.Proxy/Models/ExternalProxy.cs
index 880e87ac..2fa4f6b2 100644
--- a/src/Titanium.Web.Proxy/Models/ExternalProxy.cs
+++ b/src/Titanium.Web.Proxy/Models/ExternalProxy.cs
@@ -58,8 +58,14 @@ public ExternalProxy(string hostName, int port, string userName, string password
///
public bool BypassLocalhost { get; set; }
+ ///
+ /// Proxy type.
+ ///
public ExternalProxyType ProxyType { get; set; }
+ ///
+ /// Should DNS requests be proxied?
+ ///
public bool ProxyDnsRequests { get; set; }
///
@@ -110,6 +116,9 @@ public override string ToString()
}
}
+///
+/// Type of external proxy server.
+///
public enum ExternalProxyType
{
/// A HTTP/HTTPS proxy server.
diff --git a/src/Titanium.Web.Proxy/Models/HttpHeader.cs b/src/Titanium.Web.Proxy/Models/HttpHeader.cs
index e2374aef..da788a24 100644
--- a/src/Titanium.Web.Proxy/Models/HttpHeader.cs
+++ b/src/Titanium.Web.Proxy/Models/HttpHeader.cs
@@ -36,6 +36,9 @@ public class HttpHeader
internal static readonly Encoding DefaultEncoding = Encoding.GetEncoding("ISO-8859-1");
+ ///
+ /// Default encoding used in headers.
+ ///
public static Encoding Encoding => DefaultEncoding;
internal static readonly HttpHeader ProxyConnectionKeepAlive = new("Proxy-Connection", "keep-alive");
@@ -107,6 +110,9 @@ private protected HttpHeader(ByteString name, ByteString value, bool headerEntry
internal ByteString ValueData { get; private set; }
+ ///
+ /// Header Size.
+ ///
public int Size => Name.Length + Value.Length + HttpHeaderOverhead;
internal static int SizeOf(ByteString name, ByteString value)
diff --git a/src/Titanium.Web.Proxy/Models/IExternalProxy.cs b/src/Titanium.Web.Proxy/Models/IExternalProxy.cs
index b91a9cae..26af7cc4 100644
--- a/src/Titanium.Web.Proxy/Models/IExternalProxy.cs
+++ b/src/Titanium.Web.Proxy/Models/IExternalProxy.cs
@@ -1,40 +1,54 @@
namespace Titanium.Web.Proxy.Models;
+///
+/// The IExternalProxy interface defines the contract for an external proxy.
+/// It provides properties for configuring the proxy's credentials, host, port, and other settings.
+///
public interface IExternalProxy
{
///
- /// Use default windows credentials?
+ /// Gets or sets a value indicating whether to use default windows credentials.
///
bool UseDefaultCredentials { get; set; }
///
- /// Bypass this proxy for connections to localhost?
+ /// Gets or sets a value indicating whether to bypass this proxy for connections to localhost.
///
bool BypassLocalhost { get; set; }
+ ///
+ /// Gets or sets the type of the external proxy.
+ ///
ExternalProxyType ProxyType { get; set; }
+ ///
+ /// Gets or sets a value indicating whether to proxy DNS requests.
+ ///
bool ProxyDnsRequests { get; set; }
///
- /// Username.
+ /// Gets or sets the username for the proxy.
///
string? UserName { get; set; }
///
- /// Password.
+ /// Gets or sets the password for the proxy.
///
string? Password { get; set; }
///
- /// Host name.
+ /// Gets or sets the host name of the proxy.
///
string HostName { get; set; }
///
- /// Port.
+ /// Gets or sets the port number of the proxy.
///
int Port { get; set; }
+ ///
+ /// Returns a string that represents the current object.
+ ///
+ /// A string that represents the current object.
string ToString();
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Models/ProxyAuthenticationContext.cs b/src/Titanium.Web.Proxy/Models/ProxyAuthenticationContext.cs
index a34491bc..ea3b11c1 100644
--- a/src/Titanium.Web.Proxy/Models/ProxyAuthenticationContext.cs
+++ b/src/Titanium.Web.Proxy/Models/ProxyAuthenticationContext.cs
@@ -1,26 +1,29 @@
namespace Titanium.Web.Proxy.Models;
-
+///
+/// The ProxyAuthenticationResult enumeration represents the possible results of a proxy authentication attempt.
+/// It provides values for indicating success, failure due to invalid credentials, and other potential outcomes.
+///
public enum ProxyAuthenticationResult
{
///
- /// Indicates the authentication request was successful
+ /// Indicates the authentication request was successful.
///
Success,
///
- /// Indicates the authentication request failed
+ /// Indicates the authentication request failed.
///
Failure,
///
- /// Indicates that this stage of the authentication request succeeded
- /// And a second pass of the handshake needs to occur
+ /// Indicates that this stage of the authentication request succeeded
+ /// And a second pass of the handshake needs to occur
///
ContinuationNeeded
}
///
-/// A context container for authentication flows
+/// A context container for authentication flows
///
public class ProxyAuthenticationContext
{
@@ -34,6 +37,10 @@ public class ProxyAuthenticationContext
///
public string? Continuation { get; set; }
+ ///
+ /// Creates a new ProxyAuthenticationContext instance representing a failed authentication attempt.
+ ///
+ /// A new ProxyAuthenticationContext instance with Result set to Failure and Continuation set to null.
public static ProxyAuthenticationContext Failed()
{
return new ProxyAuthenticationContext
@@ -43,6 +50,10 @@ public static ProxyAuthenticationContext Failed()
};
}
+ ///
+ /// Creates a new ProxyAuthenticationContext instance representing a successful authentication attempt.
+ ///
+ /// A new ProxyAuthenticationContext instance with Result set to Success and Continuation set to null.
public static ProxyAuthenticationContext Succeeded()
{
return new ProxyAuthenticationContext
diff --git a/src/Titanium.Web.Proxy/Models/ProxyProtocolType.cs b/src/Titanium.Web.Proxy/Models/ProxyProtocolType.cs
index a292321e..c6ddb137 100644
--- a/src/Titanium.Web.Proxy/Models/ProxyProtocolType.cs
+++ b/src/Titanium.Web.Proxy/Models/ProxyProtocolType.cs
@@ -1,7 +1,12 @@
using System;
namespace Titanium.Web.Proxy.Models;
-
+///
+/// The ProxyProtocolType enumeration represents the types of protocols that a proxy can support.
+/// It is a flags enumeration, which means multiple values can be combined using bitwise operations.
+/// The values include None (indicating no protocol), Http (for HTTP protocol), Https (for HTTPS protocol),
+/// and AllHttp (for both HTTP and HTTPS protocols).
+///
[Flags]
public enum ProxyProtocolType
{
diff --git a/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs b/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs
index f8bddc32..fe6fe4d6 100644
--- a/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs
+++ b/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs
@@ -4,8 +4,19 @@
namespace Titanium.Web.Proxy.Models;
+///
+/// The TransparentBaseProxyEndPoint class is an abstract base class for endpoints that support transparent proxying.
+/// It inherits from the ProxyEndPoint class and provides additional functionality specific to transparent proxying,
+/// such as SSL decryption and handling of SSL authentication.
+///
public abstract class TransparentBaseProxyEndPoint : ProxyEndPoint
{
+ ///
+ /// Initializes a new instance of the TransparentBaseProxyEndPoint class with the specified IP address, port, and SSL decryption setting.
+ ///
+ /// The IP address of the endpoint.
+ /// The port of the endpoint.
+ /// A boolean value that indicates whether SSL decryption is enabled for this endpoint.
protected TransparentBaseProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl) : base(ipAddress, port,
decryptSsl)
{
diff --git a/src/Titanium.Web.Proxy/Network/BufferPool/IBufferPool.cs b/src/Titanium.Web.Proxy/Network/BufferPool/IBufferPool.cs
index f09b19de..f56b465f 100644
--- a/src/Titanium.Web.Proxy/Network/BufferPool/IBufferPool.cs
+++ b/src/Titanium.Web.Proxy/Network/BufferPool/IBufferPool.cs
@@ -3,16 +3,32 @@
namespace Titanium.Web.Proxy.StreamExtended.BufferPool;
///
-/// Use this interface to implement custom buffer pool.
-/// To use the default buffer pool implementation use DefaultBufferPool class.
+/// The IBufferPool interface defines the contract for a custom buffer pool.
+/// To use the default buffer pool implementation, use the DefaultBufferPool class.
///
public interface IBufferPool : IDisposable
{
+ ///
+ /// Gets the size of the buffer.
+ ///
int BufferSize { get; }
+ ///
+ /// Retrieves a buffer from the pool.
+ ///
+ /// A byte array representing the buffer.
byte[] GetBuffer();
+ ///
+ /// Retrieves a buffer of a specific size from the pool.
+ ///
+ /// The size of the buffer to retrieve.
+ /// A byte array representing the buffer.
byte[] GetBuffer(int bufferSize);
+ ///
+ /// Returns a buffer to the pool.
+ ///
+ /// The buffer to return to the pool.
void ReturnBuffer(byte[] buffer);
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Network/Readers/IHttpStreamReader.cs b/src/Titanium.Web.Proxy/Network/Readers/IHttpStreamReader.cs
index 306c2a20..9963ccbb 100644
--- a/src/Titanium.Web.Proxy/Network/Readers/IHttpStreamReader.cs
+++ b/src/Titanium.Web.Proxy/Network/Readers/IHttpStreamReader.cs
@@ -4,12 +4,42 @@
namespace Titanium.Web.Proxy.StreamExtended.Network;
+///
+/// The IHttpStreamReader interface defines the contract for a reader that can read HTTP data from a stream.
+/// It provides methods for reading bytes and copying the body of an HTTP message, either synchronously or asynchronously.
+/// This interface is designed to be used in the context of network streams, where data is often read in a line-by-line manner.
+///
public interface IHttpStreamReader : ILineStream
{
+ ///
+ /// Reads a sequence of bytes from the stream.
+ ///
+ /// The buffer to write data into.
+ /// The zero-based byte offset in buffer at which to begin storing the data read from the stream.
+ /// The maximum number of bytes to be read from the stream.
+ /// The total number of bytes read into the buffer.
int Read(byte[] buffer, int offset, int count);
+ ///
+ /// Asynchronously reads a sequence of bytes from the stream.
+ ///
+ /// The buffer to write data into.
+ /// The zero-based byte offset in buffer at which to begin storing the data read from the stream.
+ /// The maximum number of bytes to be read from the stream.
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A Task that represents the asynchronous read operation. The value of the TResult parameter contains the total number of bytes read into the buffer.
Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
+ ///
+ /// Asynchronously copies the body of an HTTP message to a writer.
+ ///
+ /// The IHttpStreamWriter to which the body should be copied.
+ /// A boolean value indicating whether the body is chunked.
+ /// The length of the content to be copied.
+ /// A boolean value indicating whether the body is a request.
+ /// The SessionEventArgs associated with the HTTP session.
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A Task that represents the asynchronous copy operation.
Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength,
bool isRequest, SessionEventArgs args, CancellationToken cancellationToken);
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Network/Streams/ILineStream.cs b/src/Titanium.Web.Proxy/Network/Streams/ILineStream.cs
index 6d8eee36..c3a1414c 100644
--- a/src/Titanium.Web.Proxy/Network/Streams/ILineStream.cs
+++ b/src/Titanium.Web.Proxy/Network/Streams/ILineStream.cs
@@ -2,22 +2,35 @@
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network;
-
+///
+/// The ILineStream interface defines the contract for a stream that supports line-by-line reading of data.
+/// It provides methods for filling a buffer asynchronously, reading a byte from the buffer, and reading a line asynchronously.
+/// This interface is designed to be used in the context of network streams, where data is often read in a line-by-line manner.
+///
public interface ILineStream
{
+ ///
+ /// Gets a value indicating whether data is available in the internal buffer.
+ ///
bool DataAvailable { get; }
///
- /// Fills the buffer asynchronous.
+ /// Asynchronously fills the internal buffer with data from the stream.
///
- ///
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A ValueTask that completes when the buffer has been filled, yielding a boolean indicating whether any data was read.
ValueTask FillBufferAsync(CancellationToken cancellationToken = default);
+ ///
+ /// Reads a single byte from the internal buffer.
+ ///
+ /// The byte read from the buffer.
byte ReadByteFromBuffer();
///
- /// Read a line from the byte stream
+ /// Asynchronously reads a line of data from the stream.
///
- ///
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A ValueTask that completes when the line has been read, yielding the line as a string, or null if the end of the stream has been reached.
ValueTask ReadLineAsync(CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Network/Streams/IPeekStream.cs b/src/Titanium.Web.Proxy/Network/Streams/IPeekStream.cs
index 0c2e5159..41313913 100644
--- a/src/Titanium.Web.Proxy/Network/Streams/IPeekStream.cs
+++ b/src/Titanium.Web.Proxy/Network/Streams/IPeekStream.cs
@@ -4,33 +4,38 @@
namespace Titanium.Web.Proxy.StreamExtended.Network;
+///
+/// The IPeekStream interface defines the contract for a stream that supports peeking at its data without consuming it.
+/// It provides methods for peeking at a single byte or multiple bytes, either synchronously or asynchronously.
+/// This interface is designed to be used in the context of network streams, where it is often necessary to look ahead in the data without consuming it.
+///
public interface IPeekStream
{
///
- /// Peeks a byte from buffer.
+ /// Peeks at a single byte from the buffer at the specified index.
///
- /// The index.
- ///
- /// Index is out of buffer size
+ /// The index in the buffer to peek at.
+ /// The byte at the specified index in the buffer.
+ /// Thrown when the index is out of the buffer size.
byte PeekByteFromBuffer(int index);
///
- /// Peeks a byte asynchronous.
+ /// Asynchronously peeks at a single byte from the buffer at the specified index.
///
- /// The index.
- /// The cancellation token.
- ///
+ /// The index in the buffer to peek at.
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A ValueTask that completes when the byte has been peeked, yielding the byte as an integer.
ValueTask PeekByteAsync(int index, CancellationToken cancellationToken = default);
///
- /// Peeks bytes asynchronous.
+ /// Asynchronously peeks at multiple bytes from the buffer, copying them into the provided buffer.
///
- /// The buffer to copy.
- /// The offset where copying.
- /// The index.
- /// The count.
- /// The cancellation token.
- ///
+ /// The buffer to copy the bytes into.
+ /// The offset in the destination buffer at which to start copying.
+ /// The index in the source buffer at which to start peeking.
+ /// The number of bytes to peek.
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A ValueTask that completes when the bytes have been peeked, yielding the number of bytes peeked as an integer.
ValueTask PeekBytesAsync(byte[] buffer, int offset, int index, int count,
CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Network/Writers/IHttpStreamWriter.cs b/src/Titanium.Web.Proxy/Network/Writers/IHttpStreamWriter.cs
index 65b43aa2..6038fe67 100644
--- a/src/Titanium.Web.Proxy/Network/Writers/IHttpStreamWriter.cs
+++ b/src/Titanium.Web.Proxy/Network/Writers/IHttpStreamWriter.cs
@@ -4,17 +4,47 @@
namespace Titanium.Web.Proxy.StreamExtended.Network;
///
-/// A concrete implementation of this interface is required when calling CopyStream.
+/// The IHttpStreamWriter interface defines the contract for a writer that can write HTTP data to a stream.
+/// It provides methods for writing bytes, writing a line, and writing a line with a specified value, either synchronously or asynchronously.
+/// This interface is designed to be used in the context of network streams, where data is often written in a line-by-line manner.
///
public interface IHttpStreamWriter
{
+ ///
+ /// Gets a value indicating whether the underlying stream is a network stream.
+ ///
bool IsNetworkStream { get; }
+ ///
+ /// Writes a sequence of bytes to the stream.
+ ///
+ /// The buffer to write data from.
+ /// The zero-based byte offset in buffer at which to begin copying bytes to the stream.
+ /// The number of bytes to be written to the stream.
void Write(byte[] buffer, int offset, int count);
+ ///
+ /// Asynchronously writes a sequence of bytes to the stream.
+ ///
+ /// The buffer to write data from.
+ /// The zero-based byte offset in buffer at which to begin copying bytes to the stream.
+ /// The number of bytes to be written to the stream.
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A Task that represents the asynchronous write operation.
Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
+ ///
+ /// Asynchronously writes a newline character to the stream.
+ ///
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A ValueTask that represents the asynchronous write operation.
ValueTask WriteLineAsync(CancellationToken cancellationToken = default);
+ ///
+ /// Asynchronously writes a string followed by a newline character to the stream.
+ ///
+ /// The string to write to the stream.
+ /// A CancellationToken to observe while waiting for the task to complete.
+ /// A ValueTask that represents the asynchronous write operation.
ValueTask WriteLineAsync(string value, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/ProxyServer.cs b/src/Titanium.Web.Proxy/ProxyServer.cs
index 08d37152..b897a320 100644
--- a/src/Titanium.Web.Proxy/ProxyServer.cs
+++ b/src/Titanium.Web.Proxy/ProxyServer.cs
@@ -941,6 +941,9 @@ private void ThrowNotSupportedException([CallerMemberName]string? caller = null)
private bool disposed;
+ ///
+ /// Dispose the ProxyServer instance, and stop the proxy server if running.
+ ///
protected virtual void Dispose(bool disposing)
{
if (disposed) return;
@@ -966,12 +969,14 @@ protected virtual void Dispose(bool disposing)
}
}
+ ///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
+ ///
~ProxyServer()
{
Dispose(false);
diff --git a/src/Titanium.Web.Proxy/WebSocket/WebSocketDecoder.cs b/src/Titanium.Web.Proxy/WebSocket/WebSocketDecoder.cs
index 99e9282c..6c6af581 100644
--- a/src/Titanium.Web.Proxy/WebSocket/WebSocketDecoder.cs
+++ b/src/Titanium.Web.Proxy/WebSocket/WebSocketDecoder.cs
@@ -4,7 +4,11 @@
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy;
-
+///
+/// The WebSocketDecoder class is responsible for decoding WebSocket frames from a stream of bytes.
+/// It uses a buffer to store incoming data and decodes frames from this buffer as they become available.
+/// This class is designed to be used in the context of a WebSocket connection, where frames are used to send and receive data.
+///
public class WebSocketDecoder
{
private byte[] buffer;
@@ -16,6 +20,13 @@ internal WebSocketDecoder(IBufferPool bufferPool)
buffer = new byte[bufferPool.BufferSize];
}
+ ///
+ /// Decodes WebSocket frames from the provided data.
+ ///
+ /// The data to decode frames from.
+ /// The offset in the data at which to start decoding.
+ /// The number of bytes in the data to decode.
+ /// An IEnumerable of WebSocketFrame representing the decoded frames.
public IEnumerable Decode(byte[] data, int offset, int count)
{
var buffer = data.AsMemory(offset, count);
diff --git a/src/Titanium.Web.Proxy/WebSocket/WebSocketFrame.cs b/src/Titanium.Web.Proxy/WebSocket/WebSocketFrame.cs
index 329163e5..00edbc81 100644
--- a/src/Titanium.Web.Proxy/WebSocket/WebSocketFrame.cs
+++ b/src/Titanium.Web.Proxy/WebSocket/WebSocketFrame.cs
@@ -3,19 +3,42 @@
namespace Titanium.Web.Proxy;
+///
+/// The WebSocketFrame class represents a single frame of data in a WebSocket connection.
+/// It provides properties for accessing the finality, operation code, and data of the frame,
+/// as well as methods for getting the data as a text string.
+///
public class WebSocketFrame
{
+ ///
+ /// Gets a value indicating whether this frame is the final frame in a message.
+ ///
public bool IsFinal { get; internal set; }
+ ///
+ /// Gets the operation code for this frame, which indicates the type of data contained in the frame.
+ ///
public WebsocketOpCode OpCode { get; internal set; }
+ ///
+ /// Gets the data contained in this frame as a read-only memory of bytes.
+ ///
public ReadOnlyMemory Data { get; internal set; }
+ ///
+ /// Gets the data contained in this frame as a text string, using UTF-8 encoding.
+ ///
+ /// The data as a text string.
public string GetText()
{
return GetText(Encoding.UTF8);
}
+ ///
+ /// Gets the data contained in this frame as a text string, using the specified encoding.
+ ///
+ /// The encoding to use when converting the data to a string.
+ /// The data as a text string.
public string GetText(Encoding encoding)
{
#if NET6_0_OR_GREATER
diff --git a/src/Titanium.Web.Proxy/WebSocket/WebsocketOpCode.cs b/src/Titanium.Web.Proxy/WebSocket/WebsocketOpCode.cs
index bb61f6f9..56b75a2f 100644
--- a/src/Titanium.Web.Proxy/WebSocket/WebsocketOpCode.cs
+++ b/src/Titanium.Web.Proxy/WebSocket/WebsocketOpCode.cs
@@ -1,11 +1,38 @@
namespace Titanium.Web.Proxy;
+///
+/// The WebsocketOpCode enumeration represents the operation codes for WebSocket frames.
+/// These codes are used to indicate the type of data contained in a WebSocket message frame.
+///
public enum WebsocketOpCode : byte
{
+ ///
+ /// Indicates a continuation frame.
+ ///
Continuation,
+
+ ///
+ /// Indicates a text frame.
+ ///
Text,
+
+ ///
+ /// Indicates a binary frame.
+ ///
Binary,
+
+ ///
+ /// Indicates a connection close frame.
+ ///
ConnectionClose = 8,
+
+ ///
+ /// Indicates a ping frame.
+ ///
Ping,
+
+ ///
+ /// Indicates a pong frame.
+ ///
Pong
}
\ No newline at end of file
From e3403c48531228d5205cba1d3fad35b621de15c8 Mon Sep 17 00:00:00 2001
From: Stephan van Rooij <1292510+svrooij@users.noreply.github.com>
Date: Thu, 6 Jun 2024 21:28:26 +0000
Subject: [PATCH 4/4] docs: A whole lot of additional public types documented
---
.../Makers/WinCertificateMaker.cs | 132 ++++++++++++++++++
.../EventArguments/SessionEventArgsBase.cs | 42 +++++-
.../Http2/Hpack/HpackUtil.cs | 31 +++-
.../Network/Models/TaskResult.cs | 46 +++++-
.../Network/Ssl/ClientHelloInfo.cs | 48 ++++++-
.../Network/Ssl/ServerHelloInfo.cs | 46 +++++-
.../Network/Ssl/SslTools.cs | 2 +-
7 files changed, 329 insertions(+), 18 deletions(-)
diff --git a/src/Titanium.Web.Proxy/Certificates/Makers/WinCertificateMaker.cs b/src/Titanium.Web.Proxy/Certificates/Makers/WinCertificateMaker.cs
index dc346869..8af7d161 100644
--- a/src/Titanium.Web.Proxy/Certificates/Makers/WinCertificateMaker.cs
+++ b/src/Titanium.Web.Proxy/Certificates/Makers/WinCertificateMaker.cs
@@ -305,42 +305,174 @@ private X509Certificate2 MakeCertificate(string subject, string fullSubject,
#pragma warning restore
+///
+/// The EncodingType enumeration represents the different encoding types that can be used when creating a certificate.
+///
public enum EncodingType
{
+ ///
+ /// Represents any encoding type.
+ ///
XcnCryptStringAny = 7,
+
+ ///
+ /// Represents Base64 encoding.
+ ///
XcnCryptStringBase64 = 1,
+
+ ///
+ /// Represents any Base64 encoding.
+ ///
XcnCryptStringBase64Any = 6,
+
+ ///
+ /// Represents Base64 encoding with a header.
+ ///
XcnCryptStringBase64Header = 0,
+
+ ///
+ /// Represents Base64 encoding with a request header.
+ ///
XcnCryptStringBase64Requestheader = 3,
+
+ ///
+ /// Represents Base64 encoding for URIs.
+ ///
XcnCryptStringBase64Uri = 13,
+
+ ///
+ /// Represents Base64 encoding with a X509 CRL header.
+ ///
XcnCryptStringBase64X509Crlheader = 9,
+
+ ///
+ /// Represents binary encoding.
+ ///
XcnCryptStringBinary = 2,
+
+ ///
+ /// Represents chain encoding.
+ ///
XcnCryptStringChain = 0x100,
+
+ ///
+ /// Represents the encode mask.
+ ///
XcnCryptStringEncodemask = 0xff,
+
+ ///
+ /// Represents hash data encoding.
+ ///
XcnCryptStringHashdata = 0x10000000,
+
+ ///
+ /// Represents hexadecimal encoding.
+ ///
XcnCryptStringHex = 4,
+
+ ///
+ /// Represents any hexadecimal encoding.
+ ///
XcnCryptStringHexAny = 8,
+
+ ///
+ /// Represents hexadecimal address encoding.
+ ///
XcnCryptStringHexaddr = 10,
+
+ ///
+ /// Represents hexadecimal ASCII encoding.
+ ///
XcnCryptStringHexascii = 5,
+
+ ///
+ /// Represents hexadecimal ASCII address encoding.
+ ///
XcnCryptStringHexasciiaddr = 11,
+
+ ///
+ /// Represents raw hexadecimal encoding.
+ ///
XcnCryptStringHexraw = 12,
+
+ ///
+ /// Represents encoding with no carriage return.
+ ///
XcnCryptStringNocr = -2147483648,
+
+ ///
+ /// Represents encoding with no CRLF.
+ ///
XcnCryptStringNocrlf = 0x40000000,
+
+ ///
+ /// Represents percent escape encoding.
+ ///
XcnCryptStringPercentescape = 0x8000000,
+
+ ///
+ /// Represents strict encoding.
+ ///
XcnCryptStringStrict = 0x20000000,
+
+ ///
+ /// Represents text encoding.
+ ///
XcnCryptStringText = 0x200
}
+///
+/// The AlternativeNameType enumeration represents the different types of alternative names that can be used in a certificate.
+///
public enum AlternativeNameType
{
+ ///
+ /// Represents a directory name.
+ ///
XcnCertAltNameDirectoryName = 5,
+
+ ///
+ /// Represents a DNS name.
+ ///
XcnCertAltNameDnsName = 3,
+
+ ///
+ /// Represents a GUID.
+ ///
XcnCertAltNameGuid = 10,
+
+ ///
+ /// Represents an IP address.
+ ///
XcnCertAltNameIpAddress = 8,
+
+ ///
+ /// Represents an other name.
+ ///
XcnCertAltNameOtherName = 1,
+
+ ///
+ /// Represents a registered ID.
+ ///
XcnCertAltNameRegisteredId = 9,
+
+ ///
+ /// Represents an RFC 822 name.
+ ///
XcnCertAltNameRfc822Name = 2,
+
+ ///
+ /// Represents an unknown name type.
+ ///
XcnCertAltNameUnknown = 0,
+
+ ///
+ /// Represents a URL.
+ ///
XcnCertAltNameUrl = 7,
+
+ ///
+ /// Represents a user principle name.
+ ///
XcnCertAltNameUserPrincipleName = 11
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
index dba34e4d..0bbc8473 100644
--- a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
+++ b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
@@ -13,24 +13,38 @@
namespace Titanium.Web.Proxy.EventArguments;
///
-/// 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.
+/// 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.
///
public abstract class SessionEventArgsBase : ProxyEventArgsBase, IDisposable
{
+ ///
+ /// Buffer pool used for the session.
+ ///
protected readonly IBufferPool BufferPool;
+ ///
+ /// Cancellation token source for the session.
+ ///
internal readonly CancellationTokenSource CancellationTokenSource;
+
+ ///
+ /// Exception handler function for the session.
+ ///
protected readonly ExceptionHandler? ExceptionFunc;
+
+ ///
+ /// Logger instance for the session.
+ ///
internal readonly ILogger logger;
private bool disposed;
private bool enableWinAuth;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
HttpClientStream clientStream, ConnectRequest? connectRequest, Request request,
@@ -61,8 +75,14 @@ private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoin
internal HttpClientStream ClientStream { get; }
+ ///
+ /// Unique identifier of this session, on the client side.
+ ///
public Guid ClientConnectionId => ClientConnection.Id;
+ ///
+ /// Unique identifier of this session, on the server side.
+ ///
public Guid ServerConnectionId => HttpClient.HasConnection ? ServerConnection.Id : Guid.Empty;
///
@@ -154,17 +174,26 @@ public bool EnableWinAuth
///
public Exception? Exception { get; internal set; }
+ ///
+ /// Dispose this instance.
+ ///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
+ ///
+ /// Called when an exception is thrown in user event.
+ ///
protected void OnException(Exception exception)
{
ExceptionFunc?.Invoke(exception);
}
+ ///
+ /// Dispose this instance.
+ ///
protected virtual void Dispose(bool disposing)
{
if (disposed) return;
@@ -183,6 +212,9 @@ protected virtual void Dispose(bool disposing)
disposed = true;
}
+ ///
+ /// Finalizer.
+ ///
~SessionEventArgsBase()
{
#if DEBUG
diff --git a/src/Titanium.Web.Proxy/Http2/Hpack/HpackUtil.cs b/src/Titanium.Web.Proxy/Http2/Hpack/HpackUtil.cs
index ec0d2a10..40c3d411 100644
--- a/src/Titanium.Web.Proxy/Http2/Hpack/HpackUtil.cs
+++ b/src/Titanium.Web.Proxy/Http2/Hpack/HpackUtil.cs
@@ -17,20 +17,35 @@
namespace Titanium.Web.Proxy.Http2.Hpack;
+///
+/// HPACK util
+///
public static class HpackUtil
{
- // Section 6.2. Literal Header Field Representation
+ ///
+ /// Section 6.2. Literal Header Field Representation
+ /// http://tools.ietf.org/html/rfc7541#section-6.2
+ ///
public enum IndexType
{
- Incremental, // Section 6.2.1. Literal Header Field with Incremental Indexing
- None, // Section 6.2.2. Literal Header Field without Indexing
- Never // Section 6.2.3. Literal Header Field never Indexed
+ /// Section 6.2.1. Literal Header Field with Incremental Indexing
+ Incremental,
+ /// Section 6.2.2. Literal Header Field without Indexing
+ None,
+ /// Section 6.2.3. Literal Header Field never Indexed
+ Never
}
+ ///
+ /// Section 6.1. Indexed Header Field Representation
+ /// http://tools.ietf.org/html/rfc7541#section-6.1
+ ///
public const int HuffmanEos = 256;
- // Appendix B: Huffman Codes
- // http://tools.ietf.org/html/rfc7541#appendix-B
+ ///
+ /// Appendix B: Huffman Codes
+ /// http://tools.ietf.org/html/rfc7541#appendix-B
+ ///
public static readonly int[] HuffmanCodes =
{
0x1ff8,
@@ -292,6 +307,10 @@ public enum IndexType
0x3fffffff // EOS
};
+ ///
+ /// The HuffmanCodeLengths array represents the lengths of the Huffman codes used in HPACK, the header compression format for HTTP/2.
+ /// The array contains 257 entries, one for each 8-bit symbol and an additional one for the EOS (end-of-string) symbol.
+ ///
public static readonly byte[] HuffmanCodeLengths =
{
13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
diff --git a/src/Titanium.Web.Proxy/Network/Models/TaskResult.cs b/src/Titanium.Web.Proxy/Network/Models/TaskResult.cs
index 783930bf..fd0d11af 100644
--- a/src/Titanium.Web.Proxy/Network/Models/TaskResult.cs
+++ b/src/Titanium.Web.Proxy/Network/Models/TaskResult.cs
@@ -5,26 +5,46 @@
namespace Titanium.Web.Proxy.StreamExtended.Network;
///
-/// Mimic a Task but you can set AsyncState
+/// Mimics a Task but allows setting of AsyncState.
///
public class TaskResult : IAsyncResult
{
private readonly Task task;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The task to be wrapped.
+ /// The state object to be associated with the task.
public TaskResult(Task pTask, object state)
{
task = pTask;
AsyncState = state;
}
+ ///
+ /// Gets the state object associated with this task.
+ ///
public object AsyncState { get; }
+ ///
+ /// Gets a WaitHandle that is used to wait for the task to complete.
+ ///
public WaitHandle AsyncWaitHandle => ((IAsyncResult)task).AsyncWaitHandle;
+ ///
+ /// Gets a value indicating whether the task completed synchronously.
+ ///
public bool CompletedSynchronously => ((IAsyncResult)task).CompletedSynchronously;
+ ///
+ /// Gets a value indicating whether the task has completed.
+ ///
public bool IsCompleted => task.IsCompleted;
+ ///
+ /// Blocks the calling thread until the task completes.
+ ///
public void GetResult()
{
task.GetAwaiter().GetResult();
@@ -32,26 +52,46 @@ public void GetResult()
}
///
-/// Mimic a Task<T> but you can set AsyncState
+/// Mimics a Task<T> but allows setting of AsyncState.
///
-///
+/// The type of the result produced by the task.
public class TaskResult : IAsyncResult
{
private readonly Task task;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The task to be wrapped.
+ /// The state object to be associated with the task.
public TaskResult(Task pTask, object state)
{
task = pTask;
AsyncState = state;
}
+ ///
+ /// Gets the result value of the task.
+ ///
public T Result => task.Result;
+ ///
+ /// Gets the state object associated with this task.
+ ///
public object AsyncState { get; }
+ ///
+ /// Gets a WaitHandle that is used to wait for the task to complete.
+ ///
public WaitHandle AsyncWaitHandle => ((IAsyncResult)task).AsyncWaitHandle;
+ ///
+ /// Gets a value indicating whether the task completed synchronously.
+ ///
public bool CompletedSynchronously => ((IAsyncResult)task).CompletedSynchronously;
+ ///
+ /// Gets a value indicating whether the task has completed.
+ ///
public bool IsCompleted => task.IsCompleted;
}
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Network/Ssl/ClientHelloInfo.cs b/src/Titanium.Web.Proxy/Network/Ssl/ClientHelloInfo.cs
index 4971e1dc..a009af38 100644
--- a/src/Titanium.Web.Proxy/Network/Ssl/ClientHelloInfo.cs
+++ b/src/Titanium.Web.Proxy/Network/Ssl/ClientHelloInfo.cs
@@ -10,7 +10,7 @@
namespace Titanium.Web.Proxy.StreamExtended;
///
-/// Wraps up the client SSL hello information.
+/// Represents the client SSL hello information.
///
public class ClientHelloInfo
{
@@ -20,6 +20,16 @@ public class ClientHelloInfo
"DEFLATE"
};
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The handshake version.
+ /// The major version.
+ /// The minor version.
+ /// The random bytes.
+ /// The session ID.
+ /// The ciphers.
+ /// The length of the client hello message.
internal ClientHelloInfo(int handshakeVersion, int majorVersion, int minorVersion, byte[] random, byte[] sessionId,
int[] ciphers, int clientHelloLength)
{
@@ -32,14 +42,29 @@ internal ClientHelloInfo(int handshakeVersion, int majorVersion, int minorVersio
ClientHelloLength = clientHelloLength;
}
+ ///
+ /// Gets the handshake version.
+ ///
public int HandshakeVersion { get; }
+ ///
+ /// Gets the major version.
+ ///
public int MajorVersion { get; }
+ ///
+ /// Gets the minor version.
+ ///
public int MinorVersion { get; }
+ ///
+ /// Gets the random bytes.
+ ///
public byte[] Random { get; }
+ ///
+ /// Gets the time derived from the random bytes.
+ ///
public DateTime Time
{
get
@@ -54,18 +79,39 @@ public DateTime Time
}
}
+ ///
+ /// Gets the session ID.
+ ///
public byte[] SessionId { get; }
+ ///
+ /// Gets the ciphers.
+ ///
public int[] Ciphers { get; }
+ ///
+ /// Gets or sets the compression data.
+ ///
public byte[]? CompressionData { get; internal set; }
+ ///
+ /// Gets the length of the client hello message.
+ ///
internal int ClientHelloLength { get; }
+ ///
+ /// Gets or sets the start position of the extensions in the client hello message.
+ ///
internal int ExtensionsStartPosition { get; set; }
+ ///
+ /// Gets or sets the extensions in the client hello message.
+ ///
public Dictionary? Extensions { get; set; }
+ ///
+ /// Gets the SSL protocol used in the client hello message.
+ ///
public SslProtocols SslProtocol
{
get
diff --git a/src/Titanium.Web.Proxy/Network/Ssl/ServerHelloInfo.cs b/src/Titanium.Web.Proxy/Network/Ssl/ServerHelloInfo.cs
index 5c614e5f..f637a862 100644
--- a/src/Titanium.Web.Proxy/Network/Ssl/ServerHelloInfo.cs
+++ b/src/Titanium.Web.Proxy/Network/Ssl/ServerHelloInfo.cs
@@ -18,6 +18,16 @@ public class ServerHelloInfo
"DEFLATE"
};
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The handshake version.
+ /// The major version.
+ /// The minor version.
+ /// The random bytes.
+ /// The session ID.
+ /// The cipher suite.
+ /// The length of the server hello message.
public ServerHelloInfo(int handshakeVersion, int majorVersion, int minorVersion, byte[] random,
byte[] sessionId, int cipherSuite, int serverHelloLength)
{
@@ -29,15 +39,29 @@ public ServerHelloInfo(int handshakeVersion, int majorVersion, int minorVersion,
CipherSuite = cipherSuite;
ServerHelloLength = serverHelloLength;
}
-
+ ///
+ /// Gets the handshake version.
+ ///
public int HandshakeVersion { get; }
+ ///
+ /// Gets the major version.
+ ///
public int MajorVersion { get; }
+ ///
+ /// Gets the minor version.
+ ///
public int MinorVersion { get; }
+ ///
+ /// Gets the random bytes.
+ ///
public byte[] Random { get; }
+ ///
+ /// Gets the time derived from the random bytes.
+ ///
public DateTime Time
{
get
@@ -52,16 +76,34 @@ public DateTime Time
}
}
+ ///
+ /// Gets the session ID.
+ ///
public byte[] SessionId { get; }
+ ///
+ /// Gets the cipher suite.
+ ///
public int CipherSuite { get; }
+ ///
+ /// Gets or sets the compression method.
+ ///
public byte CompressionMethod { get; set; }
+ ///
+ /// Gets the length of the server hello message.
+ ///
internal int ServerHelloLength { get; }
- internal int EntensionsStartPosition { get; set; }
+ ///
+ /// Gets or sets the start position of the extensions in the server hello message.
+ ///
+ internal int ExtensionsStartPosition { get; set; }
+ ///
+ /// Gets or sets the extensions in the server hello message.
+ ///
public Dictionary? Extensions { get; set; }
private static string SslVersionToString(int major, int minor)
diff --git a/src/Titanium.Web.Proxy/Network/Ssl/SslTools.cs b/src/Titanium.Web.Proxy/Network/Ssl/SslTools.cs
index 1b419d58..eebef253 100644
--- a/src/Titanium.Web.Proxy/Network/Ssl/SslTools.cs
+++ b/src/Titanium.Web.Proxy/Network/Ssl/SslTools.cs
@@ -248,7 +248,7 @@ public static async Task IsServerHello(IPeekStream stream, IBufferPool buf
peekStream.Position)
{
CompressionMethod = compressionMethod,
- EntensionsStartPosition = extensionsStartPosition,
+ ExtensionsStartPosition = extensionsStartPosition,
Extensions = extensions
};