Commit 8022c434 authored by Rob Garrett's avatar Rob Garrett

Resharper cleanup

parent 4ef9a02d
using System; using System;
using System.Linq;
using System.Net.Security; using System.Net.Security;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -26,11 +25,13 @@ namespace Titanium.Web.Proxy ...@@ -26,11 +25,13 @@ namespace Titanium.Web.Proxy
//if user callback is registered then do it //if user callback is registered then do it
if (ServerCertificateValidationCallback != null) if (ServerCertificateValidationCallback != null)
{ {
var args = new CertificateValidationEventArgs(); var args = new CertificateValidationEventArgs
{
Certificate = certificate,
Chain = chain,
SslPolicyErrors = sslPolicyErrors
};
args.Certificate = certificate;
args.Chain = chain;
args.SslPolicyErrors = sslPolicyErrors;
Delegate[] invocationList = ServerCertificateValidationCallback.GetInvocationList(); Delegate[] invocationList = ServerCertificateValidationCallback.GetInvocationList();
...@@ -73,7 +74,6 @@ namespace Titanium.Web.Proxy ...@@ -73,7 +74,6 @@ namespace Titanium.Web.Proxy
string[] acceptableIssuers) string[] acceptableIssuers)
{ {
X509Certificate clientCertificate = null; X509Certificate clientCertificate = null;
var customSslStream = sender as SslStream;
if (acceptableIssuers != null && if (acceptableIssuers != null &&
acceptableIssuers.Length > 0 && acceptableIssuers.Length > 0 &&
...@@ -100,13 +100,15 @@ namespace Titanium.Web.Proxy ...@@ -100,13 +100,15 @@ namespace Titanium.Web.Proxy
//If user call back is registered //If user call back is registered
if (ClientCertificateSelectionCallback != null) if (ClientCertificateSelectionCallback != null)
{ {
var args = new CertificateSelectionEventArgs(); var args = new CertificateSelectionEventArgs
{
TargetHost = targetHost,
LocalCertificates = localCertificates,
RemoteCertificate = remoteCertificate,
AcceptableIssuers = acceptableIssuers,
ClientCertificate = clientCertificate
};
args.TargetHost = targetHost;
args.LocalCertificates = localCertificates;
args.RemoteCertificate = remoteCertificate;
args.AcceptableIssuers = acceptableIssuers;
args.ClientCertificate = clientCertificate;
Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList(); Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length]; Task[] handlerTasks = new Task[invocationList.Length];
......
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Decompression namespace Titanium.Web.Proxy.Decompression
{ {
......
...@@ -8,12 +8,29 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -8,12 +8,29 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public class CertificateSelectionEventArgs : EventArgs public class CertificateSelectionEventArgs : EventArgs
{ {
/// <summary>
/// Sender object.
/// </summary>
public object Sender { get; internal set; } public object Sender { get; internal set; }
/// <summary>
/// Target host.
/// </summary>
public string TargetHost { get; internal set; } public string TargetHost { get; internal set; }
/// <summary>
/// Local certificates.
/// </summary>
public X509CertificateCollection LocalCertificates { get; internal set; } public X509CertificateCollection LocalCertificates { get; internal set; }
/// <summary>
/// Remote certificate.
/// </summary>
public X509Certificate RemoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; internal set; }
/// <summary>
/// Acceptable issuers.
/// </summary>
public string[] AcceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; internal set; }
/// <summary>
/// Client Certificate.
/// </summary>
public X509Certificate ClientCertificate { get; set; } public X509Certificate ClientCertificate { get; set; }
} }
......
...@@ -7,17 +7,24 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -7,17 +7,24 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// An argument passed on to the user for validating the server certificate during SSL authentication /// An argument passed on to the user for validating the server certificate during SSL authentication
/// </summary> /// </summary>
public class CertificateValidationEventArgs : EventArgs, IDisposable public class CertificateValidationEventArgs : EventArgs
{ {
/// <summary>
/// Certificate
/// </summary>
public X509Certificate Certificate { get; internal set; } public X509Certificate Certificate { get; internal set; }
/// <summary>
/// Certificate chain
/// </summary>
public X509Chain Chain { get; internal set; } public X509Chain Chain { get; internal set; }
/// <summary>
/// SSL policy errors.
/// </summary>
public SslPolicyErrors SslPolicyErrors { get; internal set; } public SslPolicyErrors SslPolicyErrors { get; internal set; }
/// <summary>
/// is a valid certificate?
/// </summary>
public bool IsValid { get; set; } public bool IsValid { get; set; }
public void Dispose()
{
}
} }
} }
...@@ -44,7 +44,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -44,7 +44,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public Guid Id => WebSession.RequestId; public Guid Id => WebSession.RequestId;
//Should we send a rerequest /// <summary>
/// Should we send a rerequest
/// </summary>
public bool ReRequest public bool ReRequest
{ {
get; get;
...@@ -56,7 +58,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -56,7 +58,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public bool IsHttps => WebSession.Request.RequestUri.Scheme == Uri.UriSchemeHttps; public bool IsHttps => WebSession.Request.RequestUri.Scheme == Uri.UriSchemeHttps;
/// <summary>
/// Client End Point.
/// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint; public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;
/// <summary> /// <summary>
...@@ -65,8 +69,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -65,8 +69,14 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public HttpWebClient WebSession { get; set; } public HttpWebClient WebSession { get; set; }
/// <summary>
/// Are we using a custom upstream HTTP proxy?
/// </summary>
public ExternalProxy CustomUpStreamHttpProxyUsed { get; set; } public ExternalProxy CustomUpStreamHttpProxyUsed { get; set; }
/// <summary>
/// Are we using a custom upstream HTTPS proxy?
/// </summary>
public ExternalProxy CustomUpStreamHttpsProxyUsed { get; set; } public ExternalProxy CustomUpStreamHttpsProxyUsed { get; set; }
/// <summary> /// <summary>
...@@ -105,7 +115,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -105,7 +115,7 @@ namespace Titanium.Web.Proxy.EventArguments
//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 (WebSession.Request.IsChunked) if (WebSession.Request.IsChunked)
{ {
await this.ProxyClient.ClientStreamReader.CopyBytesToStreamChunked(bufferSize, requestBodyStream); await ProxyClient.ClientStreamReader.CopyBytesToStreamChunked(bufferSize, requestBodyStream);
} }
else else
{ {
...@@ -113,7 +123,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -113,7 +123,7 @@ namespace Titanium.Web.Proxy.EventArguments
if (WebSession.Request.ContentLength > 0) if (WebSession.Request.ContentLength > 0)
{ {
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response //If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await this.ProxyClient.ClientStreamReader.CopyBytesToStream(bufferSize, requestBodyStream, await ProxyClient.ClientStreamReader.CopyBytesToStream(bufferSize, requestBodyStream,
WebSession.Request.ContentLength); WebSession.Request.ContentLength);
} }
...@@ -431,7 +441,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -431,7 +441,7 @@ namespace Titanium.Web.Proxy.EventArguments
            await GenericResponse(html, null, status);             await GenericResponse(html, null, status);
} }
/// <summary> /// <summary>
/// Before request is made to server  /// Before request is made to server 
/// Respond with the specified HTML string to client /// Respond with the specified HTML string to client
/// and the specified status /// and the specified status
...@@ -485,12 +495,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -485,12 +495,17 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.Request.CancelRequest = true; WebSession.Request.CancelRequest = true;
} }
/// <summary>
/// Redirect to URL.
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public async Task Redirect(string url) public async Task Redirect(string url)
{ {
var response = new RedirectResponse(); var response = new RedirectResponse();
response.HttpVersion = WebSession.Request.HttpVersion; response.HttpVersion = WebSession.Request.HttpVersion;
response.ResponseHeaders.Add("Location", new Models.HttpHeader("Location", url)); response.ResponseHeaders.Add("Location", new HttpHeader("Location", url));
response.ResponseBody = Encoding.ASCII.GetBytes(string.Empty); response.ResponseBody = Encoding.ASCII.GetBytes(string.Empty);
await Respond(response); await Respond(response);
......
using System; 
namespace Titanium.Web.Proxy.Exceptions namespace Titanium.Web.Proxy.Exceptions
{ {
/// <summary> /// <summary>
...@@ -7,6 +6,10 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -7,6 +6,10 @@ namespace Titanium.Web.Proxy.Exceptions
/// </summary> /// </summary>
public class BodyNotFoundException : ProxyException public class BodyNotFoundException : ProxyException
{ {
/// <summary>
/// Constructor.
/// </summary>
/// <param name="message"></param>
public BodyNotFoundException(string message) public BodyNotFoundException(string message)
: base(message) : base(message)
{ {
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
/// <summary>
/// Extension methods for Byte Arrays.
/// </summary>
public static class ByteArrayExtensions public static class ByteArrayExtensions
{ {
/// <summary> /// <summary>
...@@ -14,7 +17,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -14,7 +17,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <returns></returns> /// <returns></returns>
public static T[] SubArray<T>(this T[] data, int index, int length) public static T[] SubArray<T>(this T[] data, int index, int length)
{ {
T[] result = new T[length]; var result = new T[length];
Array.Copy(data, index, result, 0, length); Array.Copy(data, index, result, 0, length);
return result; return result;
} }
......
...@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Extensions
internal static bool IsConnected(this Socket client) internal static bool IsConnected(this Socket client)
{ {
// This is how you can determine whether a socket is still connected. // This is how you can determine whether a socket is still connected.
bool blockingState = client.Blocking; var blockingState = client.Blocking;
try try
{ {
byte[] tmp = new byte[1]; var tmp = new byte[1];
client.Blocking = false; client.Blocking = false;
client.Send(tmp, 0, 0); client.Send(tmp, 0, 0);
...@@ -25,14 +25,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -25,14 +25,7 @@ namespace Titanium.Web.Proxy.Extensions
catch (SocketException e) catch (SocketException e)
{ {
// 10035 == WSAEWOULDBLOCK // 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035)) return e.NativeErrorCode.Equals(10035);
{
return true;
}
else
{
return false;
}
} }
finally finally
{ {
......
...@@ -4,7 +4,6 @@ using System.IO; ...@@ -4,7 +4,6 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -16,15 +15,15 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -16,15 +15,15 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
internal class CustomBinaryReader : IDisposable internal class CustomBinaryReader : IDisposable
{ {
private Stream stream; private readonly Stream stream;
private Encoding encoding; private readonly Encoding encoding;
internal CustomBinaryReader(Stream stream) internal CustomBinaryReader(Stream stream)
{ {
this.stream = stream; this.stream = stream;
//default to UTF-8 //default to UTF-8
this.encoding = Encoding.UTF8; encoding = Encoding.UTF8;
} }
internal Stream BaseStream => stream; internal Stream BaseStream => stream;
...@@ -40,7 +39,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -40,7 +39,7 @@ namespace Titanium.Web.Proxy.Helpers
var lastChar = default(char); var lastChar = default(char);
var buffer = new byte[1]; var buffer = new byte[1];
while ((await this.stream.ReadAsync(buffer, 0, 1)) > 0) while ((await stream.ReadAsync(buffer, 0, 1)) > 0)
{ {
//if new line //if new line
if (lastChar == '\r' && buffer[0] == '\n') if (lastChar == '\r' && buffer[0] == '\n')
...@@ -82,6 +81,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -82,6 +81,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Read the specified number of raw bytes from the base stream /// Read the specified number of raw bytes from the base stream
/// </summary> /// </summary>
/// <param name="bufferSize"></param>
/// <param name="totalBytesToRead"></param> /// <param name="totalBytesToRead"></param>
/// <returns></returns> /// <returns></returns>
internal async Task<byte[]> ReadBytesAsync(int bufferSize, long totalBytesToRead) internal async Task<byte[]> ReadBytesAsync(int bufferSize, long totalBytesToRead)
...@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy.Helpers
using (var outStream = new MemoryStream()) using (var outStream = new MemoryStream())
{ {
while ((bytesRead += await this.stream.ReadAsync(buffer, 0, bytesToRead)) > 0) while ((bytesRead += await stream.ReadAsync(buffer, 0, bytesToRead)) > 0)
{ {
await outStream.WriteAsync(buffer, 0, bytesRead); await outStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
......
...@@ -8,7 +8,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,7 +8,10 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
public class FireFoxProxySettingsManager public class FireFoxProxySettingsManager
{ {
public void AddFirefox() /// <summary>
/// Add Firefox settings.
/// </summary>
public void AddFirefox()
{ {
try try
{ {
...@@ -16,21 +19,17 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -16,21 +19,17 @@ namespace Titanium.Web.Proxy.Helpers
new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
"\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default"); "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default");
var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js"; var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js";
if (File.Exists(myFfPrefFile)) if (!File.Exists(myFfPrefFile)) return;
{ // We have a pref file so let''s make sure it has the proxy setting
// We have a pref file so let''s make sure it has the proxy setting var myReader = new StreamReader(myFfPrefFile);
var myReader = new StreamReader(myFfPrefFile); var myPrefContents = myReader.ReadToEnd();
var myPrefContents = myReader.ReadToEnd(); myReader.Close();
myReader.Close(); if (!myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);")) return;
if (myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);")) // Add the proxy enable line and write it back to the file
{ myPrefContents = myPrefContents.Replace("user_pref(\"network.proxy.type\", 0);", "");
// Add the proxy enable line and write it back to the file
myPrefContents = myPrefContents.Replace("user_pref(\"network.proxy.type\", 0);", "");
File.Delete(myFfPrefFile); File.Delete(myFfPrefFile);
File.WriteAllText(myFfPrefFile, myPrefContents); File.WriteAllText(myFfPrefFile, myPrefContents);
}
}
} }
catch (Exception) catch (Exception)
{ {
...@@ -38,7 +37,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -38,7 +37,10 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
public void RemoveFirefox() /// <summary>
/// Remove firefox settings.
/// </summary>
public void RemoveFirefox()
{ {
try try
{ {
...@@ -46,20 +48,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -46,20 +48,18 @@ namespace Titanium.Web.Proxy.Helpers
new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
"\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default"); "\\Mozilla\\Firefox\\Profiles\\").GetDirectories("*.default");
var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js"; var myFfPrefFile = myProfileDirectory[0].FullName + "\\prefs.js";
if (File.Exists(myFfPrefFile)) if (!File.Exists(myFfPrefFile)) return;
// We have a pref file so let''s make sure it has the proxy setting
var myReader = new StreamReader(myFfPrefFile);
var myPrefContents = myReader.ReadToEnd();
myReader.Close();
if (!myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);"))
{ {
// We have a pref file so let''s make sure it has the proxy setting // Add the proxy enable line and write it back to the file
var myReader = new StreamReader(myFfPrefFile); myPrefContents = myPrefContents + "\n\r" + "user_pref(\"network.proxy.type\", 0);";
var myPrefContents = myReader.ReadToEnd();
myReader.Close();
if (!myPrefContents.Contains("user_pref(\"network.proxy.type\", 0);"))
{
// Add the proxy enable line and write it back to the file
myPrefContents = myPrefContents + "\n\r" + "user_pref(\"network.proxy.type\", 0);";
File.Delete(myFfPrefFile); File.Delete(myFfPrefFile);
File.WriteAllText(myFfPrefFile, myPrefContents); File.WriteAllText(myFfPrefFile, myPrefContents);
}
} }
} }
catch (Exception) catch (Exception)
......
using System; using System.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Net; using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -33,28 +29,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -33,28 +29,14 @@ namespace Titanium.Web.Proxy.Helpers
/// Adapated from below link /// Adapated from below link
/// http://stackoverflow.com/questions/11834091/how-to-check-if-localhost /// http://stackoverflow.com/questions/11834091/how-to-check-if-localhost
/// </summary> /// </summary>
/// <param name="address></param> /// <param name="address"></param>
/// <returns></returns> /// <returns></returns>
internal static bool IsLocalIpAddress(IPAddress address) internal static bool IsLocalIpAddress(IPAddress address)
{ {
try // get local IP addresses
{ var localIPs = Dns.GetHostAddresses(Dns.GetHostName());
// get local IP addresses // test if any host IP equals to any local IP or to localhost
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName()); return IPAddress.IsLoopback(address) || localIPs.Contains(address);
// test if any host IP equals to any local IP or to localhost
// is localhost
if (IPAddress.IsLoopback(address)) return true;
// is local address
foreach (IPAddress localIP in localIPs)
{
if (address.Equals(localIP)) return true;
}
}
catch { }
return false;
} }
} }
} }
...@@ -4,11 +4,8 @@ using Microsoft.Win32; ...@@ -4,11 +4,8 @@ using Microsoft.Win32;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Sockets;
/// <summary> // Helper classes for setting system proxy settings
/// Helper classes for setting system proxy settings
/// </summary>
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal enum ProxyProtocolType internal enum ProxyProtocolType
......
...@@ -140,6 +140,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -140,6 +140,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="localCertificateSelectionCallback"></param> /// <param name="localCertificateSelectionCallback"></param>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="tcpConnectionFactory"></param> /// <param name="tcpConnectionFactory"></param>
/// <param name="upStreamEndPoint"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task SendRaw(int bufferSize, int connectionTimeOutSeconds, internal static async Task SendRaw(int bufferSize, int connectionTimeOutSeconds,
string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary<string, HttpHeader> requestHeaders, string remoteHostName, int remotePort, string httpCmd, Version httpVersion, Dictionary<string, HttpHeader> requestHeaders,
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -15,17 +13,26 @@ namespace Titanium.Web.Proxy.Http ...@@ -15,17 +13,26 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class HttpWebClient public class HttpWebClient
{ {
/// <summary> /// <summary>
/// Connection to server /// Connection to server
/// </summary> /// </summary>
internal TcpConnection ServerConnection { get; set; } internal TcpConnection ServerConnection { get; set; }
public Guid RequestId { get; private set; } /// <summary>
/// Request ID.
/// </summary>
public Guid RequestId { get; }
/// <summary>
/// Headers passed with Connect.
/// </summary>
public List<HttpHeader> ConnectHeaders { get; set; } public List<HttpHeader> ConnectHeaders { get; set; }
/// <summary>
/// Web Request.
/// </summary>
public Request Request { get; set; } public Request Request { get; set; }
/// <summary>
/// Web Response.
/// </summary>
public Response Response { get; set; } public Response Response { get; set; }
/// <summary> /// <summary>
...@@ -37,15 +44,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -37,15 +44,14 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Is Https? /// Is Https?
/// </summary> /// </summary>
public bool IsHttps => this.Request.RequestUri.Scheme == Uri.UriSchemeHttps; public bool IsHttps => Request.RequestUri.Scheme == Uri.UriSchemeHttps;
internal HttpWebClient() internal HttpWebClient()
{ {
this.RequestId = Guid.NewGuid(); RequestId = Guid.NewGuid();
Request = new Request();
this.Request = new Request(); Response = new Response();
this.Response = new Response();
} }
/// <summary> /// <summary>
...@@ -65,18 +71,18 @@ namespace Titanium.Web.Proxy.Http ...@@ -65,18 +71,18 @@ namespace Titanium.Web.Proxy.Http
/// <returns></returns> /// <returns></returns>
internal async Task SendRequest(bool enable100ContinueBehaviour) internal async Task SendRequest(bool enable100ContinueBehaviour)
{ {
Stream stream = ServerConnection.Stream; var stream = ServerConnection.Stream;
StringBuilder requestLines = new StringBuilder(); var requestLines = new StringBuilder();
//prepare the request & headers //prepare the request & headers
if ((ServerConnection.UpStreamHttpProxy != null && ServerConnection.IsHttps == false) || (ServerConnection.UpStreamHttpsProxy != null && ServerConnection.IsHttps == true)) if ((ServerConnection.UpStreamHttpProxy != null && ServerConnection.IsHttps == false) || (ServerConnection.UpStreamHttpsProxy != null && ServerConnection.IsHttps))
{ {
requestLines.AppendLine(string.Join(" ", this.Request.Method, this.Request.RequestUri.AbsoluteUri, $"HTTP/{this.Request.HttpVersion.Major}.{this.Request.HttpVersion.Minor}")); requestLines.AppendLine(string.Join(" ", Request.Method, Request.RequestUri.AbsoluteUri, $"HTTP/{Request.HttpVersion.Major}.{Request.HttpVersion.Minor}"));
} }
else else
{ {
requestLines.AppendLine(string.Join(" ", this.Request.Method, this.Request.RequestUri.PathAndQuery, $"HTTP/{this.Request.HttpVersion.Major}.{this.Request.HttpVersion.Minor}")); requestLines.AppendLine(string.Join(" ", Request.Method, Request.RequestUri.PathAndQuery, $"HTTP/{Request.HttpVersion.Major}.{Request.HttpVersion.Minor}"));
} }
//Send Authentication to Upstream proxy if needed //Send Authentication to Upstream proxy if needed
...@@ -86,7 +92,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -86,7 +92,7 @@ namespace Titanium.Web.Proxy.Http
requestLines.AppendLine("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(ServerConnection.UpStreamHttpProxy.UserName + ":" + ServerConnection.UpStreamHttpProxy.Password))); requestLines.AppendLine("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(ServerConnection.UpStreamHttpProxy.UserName + ":" + ServerConnection.UpStreamHttpProxy.Password)));
} }
//write request headers //write request headers
foreach (var headerItem in this.Request.RequestHeaders) foreach (var headerItem in Request.RequestHeaders)
{ {
var header = headerItem.Value; var header = headerItem.Value;
if (headerItem.Key != "Proxy-Authorization") if (headerItem.Key != "Proxy-Authorization")
...@@ -96,7 +102,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -96,7 +102,7 @@ namespace Titanium.Web.Proxy.Http
} }
//write non unique request headers //write non unique request headers
foreach (var headerItem in this.Request.NonUniqueRequestHeaders) foreach (var headerItem in Request.NonUniqueRequestHeaders)
{ {
var headers = headerItem.Value; var headers = headerItem.Value;
foreach (var header in headers) foreach (var header in headers)
...@@ -110,15 +116,15 @@ namespace Titanium.Web.Proxy.Http ...@@ -110,15 +116,15 @@ namespace Titanium.Web.Proxy.Http
requestLines.AppendLine(); requestLines.AppendLine();
string request = requestLines.ToString(); var request = requestLines.ToString();
byte[] requestBytes = Encoding.ASCII.GetBytes(request); var requestBytes = Encoding.ASCII.GetBytes(request);
await stream.WriteAsync(requestBytes, 0, requestBytes.Length); await stream.WriteAsync(requestBytes, 0, requestBytes.Length);
await stream.FlushAsync(); await stream.FlushAsync();
if (enable100ContinueBehaviour) if (enable100ContinueBehaviour)
{ {
if (this.Request.ExpectContinue) if (Request.ExpectContinue)
{ {
var httpResult = (await ServerConnection.StreamReader.ReadLineAsync()).Split(ProxyConstants.SpaceSplit, 3); var httpResult = (await ServerConnection.StreamReader.ReadLineAsync()).Split(ProxyConstants.SpaceSplit, 3);
var responseStatusCode = httpResult[1].Trim(); var responseStatusCode = httpResult[1].Trim();
...@@ -128,13 +134,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -128,13 +134,13 @@ namespace Titanium.Web.Proxy.Http
if (responseStatusCode.Equals("100") if (responseStatusCode.Equals("100")
&& responseStatusDescription.ToLower().Equals("continue")) && responseStatusDescription.ToLower().Equals("continue"))
{ {
this.Request.Is100Continue = true; Request.Is100Continue = true;
await ServerConnection.StreamReader.ReadLineAsync(); await ServerConnection.StreamReader.ReadLineAsync();
} }
else if (responseStatusCode.Equals("417") else if (responseStatusCode.Equals("417")
&& responseStatusDescription.ToLower().Equals("expectation failed")) && responseStatusDescription.ToLower().Equals("expectation failed"))
{ {
this.Request.ExpectationFailed = true; Request.ExpectationFailed = true;
await ServerConnection.StreamReader.ReadLineAsync(); await ServerConnection.StreamReader.ReadLineAsync();
} }
} }
...@@ -148,7 +154,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -148,7 +154,7 @@ namespace Titanium.Web.Proxy.Http
internal async Task ReceiveResponse() internal async Task ReceiveResponse()
{ {
//return if this is already read //return if this is already read
if (this.Response.ResponseStatusCode != null) return; if (Response.ResponseStatusCode != null) return;
var httpResult = (await ServerConnection.StreamReader.ReadLineAsync()).Split(ProxyConstants.SpaceSplit, 3); var httpResult = (await ServerConnection.StreamReader.ReadLineAsync()).Split(ProxyConstants.SpaceSplit, 3);
...@@ -161,33 +167,33 @@ namespace Titanium.Web.Proxy.Http ...@@ -161,33 +167,33 @@ namespace Titanium.Web.Proxy.Http
var httpVersion = httpResult[0].Trim().ToLower(); var httpVersion = httpResult[0].Trim().ToLower();
var version = new Version(1, 1); var version = new Version(1, 1);
if (httpVersion == "http/1.0") if (0 == string.CompareOrdinal(httpVersion, "http/1.0"))
{ {
version = new Version(1, 0); version = new Version(1, 0);
} }
this.Response.HttpVersion = version; Response.HttpVersion = version;
this.Response.ResponseStatusCode = httpResult[1].Trim(); Response.ResponseStatusCode = httpResult[1].Trim();
this.Response.ResponseStatusDescription = httpResult[2].Trim(); Response.ResponseStatusDescription = httpResult[2].Trim();
//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 (this.Response.ResponseStatusCode.Equals("100") if (Response.ResponseStatusCode.Equals("100")
&& this.Response.ResponseStatusDescription.ToLower().Equals("continue")) && Response.ResponseStatusDescription.ToLower().Equals("continue"))
{ {
//Read the next line after 100-continue //Read the next line after 100-continue
this.Response.Is100Continue = true; Response.Is100Continue = true;
this.Response.ResponseStatusCode = null; Response.ResponseStatusCode = null;
await ServerConnection.StreamReader.ReadLineAsync(); await ServerConnection.StreamReader.ReadLineAsync();
//now receive response //now receive response
await ReceiveResponse(); await ReceiveResponse();
return; return;
} }
else if (this.Response.ResponseStatusCode.Equals("417") else if (Response.ResponseStatusCode.Equals("417")
&& this.Response.ResponseStatusDescription.ToLower().Equals("expectation failed")) && Response.ResponseStatusDescription.ToLower().Equals("expectation failed"))
{ {
//read next line after expectation failed response //read next line after expectation failed response
this.Response.ExpectationFailed = true; Response.ExpectationFailed = true;
this.Response.ResponseStatusCode = null; Response.ResponseStatusCode = null;
await ServerConnection.StreamReader.ReadLineAsync(); await ServerConnection.StreamReader.ReadLineAsync();
//now receive response //now receive response
await ReceiveResponse(); await ReceiveResponse();
......
...@@ -34,12 +34,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -34,12 +34,7 @@ namespace Titanium.Web.Proxy.Http
get get
{ {
var hasHeader = RequestHeaders.ContainsKey("host"); var hasHeader = RequestHeaders.ContainsKey("host");
if (hasHeader) return hasHeader ? RequestHeaders["host"].Value : null;
{
return RequestHeaders["host"].Value;
}
return null;
} }
set set
{ {
...@@ -154,11 +149,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -154,11 +149,11 @@ namespace Titanium.Web.Proxy.Http
if (hasHeader) if (hasHeader)
{ {
var header = RequestHeaders["content-type"]; var header = RequestHeaders["content-type"];
header.Value = value.ToString(); header.Value = value;
} }
else else
{ {
RequestHeaders.Add("content-type", new HttpHeader("content-type", value.ToString())); RequestHeaders.Add("content-type", new HttpHeader("content-type", value));
} }
} }
...@@ -219,14 +214,10 @@ namespace Titanium.Web.Proxy.Http ...@@ -219,14 +214,10 @@ namespace Titanium.Web.Proxy.Http
{ {
var hasHeader = RequestHeaders.ContainsKey("expect"); var hasHeader = RequestHeaders.ContainsKey("expect");
if (hasHeader) if (!hasHeader) return false;
{ var header = RequestHeaders["expect"];
var header = RequestHeaders["expect"];
return header.Value.Equals("100-continue");
}
return false; return header.Value.Equals("100-continue");
} }
} }
...@@ -275,13 +266,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -275,13 +266,7 @@ namespace Titanium.Web.Proxy.Http
var header = RequestHeaders["upgrade"]; var header = RequestHeaders["upgrade"];
if (header.Value.ToLower() == "websocket") return header.Value.ToLower() == "websocket";
{
return true;
}
return false;
} }
} }
...@@ -305,6 +290,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -305,6 +290,9 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
/// <summary>
/// Constructor.
/// </summary>
public Request() public Request()
{ {
RequestHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase); RequestHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase);
......
...@@ -12,7 +12,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -12,7 +12,13 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class Response public class Response
{ {
/// <summary>
/// Response Status Code.
/// </summary>
public string ResponseStatusCode { get; set; } public string ResponseStatusCode { get; set; }
/// <summary>
/// Response Status description.
/// </summary>
public string ResponseStatusDescription { get; set; } public string ResponseStatusDescription { get; set; }
internal Encoding Encoding => this.GetResponseCharacterEncoding(); internal Encoding Encoding => this.GetResponseCharacterEncoding();
...@@ -26,14 +32,10 @@ namespace Titanium.Web.Proxy.Http ...@@ -26,14 +32,10 @@ namespace Titanium.Web.Proxy.Http
{ {
var hasHeader = ResponseHeaders.ContainsKey("content-encoding"); var hasHeader = ResponseHeaders.ContainsKey("content-encoding");
if (hasHeader) if (!hasHeader) return null;
{ var header = ResponseHeaders["content-encoding"];
var header = ResponseHeaders["content-encoding"];
return header.Value.Trim(); return header.Value.Trim();
}
return null;
} }
} }
...@@ -229,10 +231,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -229,10 +231,13 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public bool ExpectationFailed { get; internal set; } public bool ExpectationFailed { get; internal set; }
/// <summary>
/// Constructor.
/// </summary>
public Response() public Response()
{ {
this.ResponseHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase); ResponseHeaders = new Dictionary<string, HttpHeader>(StringComparer.OrdinalIgnoreCase);
this.NonUniqueResponseHeaders = new Dictionary<string, List<HttpHeader>>(StringComparer.OrdinalIgnoreCase); NonUniqueResponseHeaders = new Dictionary<string, List<HttpHeader>>(StringComparer.OrdinalIgnoreCase);
} }
} }
......
...@@ -7,16 +7,25 @@ namespace Titanium.Web.Proxy.Http.Responses ...@@ -7,16 +7,25 @@ namespace Titanium.Web.Proxy.Http.Responses
    /// </summary>     /// </summary>
    public class GenericResponse : Response     public class GenericResponse : Response
    {     {
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="status"></param>
        public GenericResponse(HttpStatusCode status)         public GenericResponse(HttpStatusCode status)
        {         {
            ResponseStatusCode = ((int)status).ToString();             ResponseStatusCode = ((int)status).ToString();
            ResponseStatusDescription = status.ToString();              ResponseStatusDescription = status.ToString(); 
        }         }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="statusCode"></param>
        /// <param name="statusDescription"></param>
        public GenericResponse(string statusCode, string statusDescription)         public GenericResponse(string statusCode, string statusDescription)
        {         {
            ResponseStatusCode = statusCode;             ResponseStatusCode = statusCode;
            ResponseStatusDescription = statusCode;             ResponseStatusDescription = statusDescription;
        }         }
    }     }
} }
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
/// </summary> /// </summary>
public sealed class OkResponse : Response public sealed class OkResponse : Response
{ {
/// <summary>
/// Constructor.
/// </summary>
public OkResponse() public OkResponse()
{ {
ResponseStatusCode = "200"; ResponseStatusCode = "200";
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
/// </summary> /// </summary>
public sealed class RedirectResponse : Response public sealed class RedirectResponse : Response
{ {
/// <summary>
/// Constructor.
/// </summary>
public RedirectResponse() public RedirectResponse()
{ {
ResponseStatusCode = "302"; ResponseStatusCode = "302";
......
...@@ -10,20 +10,38 @@ namespace Titanium.Web.Proxy.Models ...@@ -10,20 +10,38 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public abstract class ProxyEndPoint public abstract class ProxyEndPoint
{ {
public ProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl) /// <summary>
/// Constructor.
/// </summary>
/// <param name="IpAddress"></param>
/// <param name="Port"></param>
/// <param name="EnableSsl"></param>
protected ProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl)
{ {
this.IpAddress = IpAddress; this.IpAddress = IpAddress;
this.Port = Port; this.Port = Port;
this.EnableSsl = EnableSsl; this.EnableSsl = EnableSsl;
} }
/// <summary>
/// Ip Address.
/// </summary>
public IPAddress IpAddress { get; internal set; } public IPAddress IpAddress { get; internal set; }
/// <summary>
/// Port.
/// </summary>
public int Port { get; internal set; } public int Port { get; internal set; }
/// <summary>
/// Enable SSL?
/// </summary>
public bool EnableSsl { get; internal set; } public bool EnableSsl { get; internal set; }
public bool IpV6Enabled => IpAddress == IPAddress.IPv6Any /// <summary>
|| IpAddress == IPAddress.IPv6Loopback /// Is IPv6 enabled?
|| IpAddress == IPAddress.IPv6None; /// </summary>
public bool IpV6Enabled => Equals(IpAddress, IPAddress.IPv6Any)
|| Equals(IpAddress, IPAddress.IPv6Loopback)
|| Equals(IpAddress, IPAddress.IPv6None);
internal TcpListener listener { get; set; } internal TcpListener listener { get; set; }
} }
...@@ -37,14 +55,26 @@ namespace Titanium.Web.Proxy.Models ...@@ -37,14 +55,26 @@ namespace Titanium.Web.Proxy.Models
internal bool IsSystemHttpProxy { get; set; } internal bool IsSystemHttpProxy { get; set; }
internal bool IsSystemHttpsProxy { get; set; } internal bool IsSystemHttpsProxy { get; set; }
public List<string> ExcludedHttpsHostNameRegex { get; set; } /// <summary>
/// List of host names to exclude using Regular Expressions.
/// </summary>
public List<string> ExcludedHttpsHostNameRegex { get; set; }
/// <summary>
/// Generic certificate to use for SSL decryption.
/// </summary>
public X509Certificate2 GenericCertificate { get; set; } public X509Certificate2 GenericCertificate { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="IpAddress"></param>
/// <param name="Port"></param>
/// <param name="EnableSsl"></param>
public ExplicitProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl) public ExplicitProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl)
: base(IpAddress, Port, EnableSsl) : base(IpAddress, Port, EnableSsl)
{ {
} }
} }
...@@ -54,13 +84,19 @@ namespace Titanium.Web.Proxy.Models ...@@ -54,13 +84,19 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class TransparentProxyEndPoint : ProxyEndPoint public class TransparentProxyEndPoint : ProxyEndPoint
{ {
//Name of the Certificate need to be sent (same as the hostname we want to proxy)
//This is valid only when UseServerNameIndication is set to false
public string GenericCertificateName { get; set; }
/// <summary>
// public bool UseServerNameIndication { get; set; } /// Name of the Certificate need to be sent (same as the hostname we want to proxy)
/// This is valid only when UseServerNameIndication is set to false
/// </summary>
public string GenericCertificateName { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="IpAddress"></param>
/// <param name="Port"></param>
/// <param name="EnableSsl"></param>
public TransparentProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl) public TransparentProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl)
: base(IpAddress, Port, EnableSsl) : base(IpAddress, Port, EnableSsl)
{ {
......
...@@ -13,10 +13,16 @@ namespace Titanium.Web.Proxy.Models ...@@ -13,10 +13,16 @@ namespace Titanium.Web.Proxy.Models
private string userName; private string userName;
private string password; private string password;
/// <summary>
/// Use default windows credentials?
/// </summary>
public bool UseDefaultCredentials { get; set; } public bool UseDefaultCredentials { get; set; }
/// <summary>
/// Username.
/// </summary>
public string UserName { public string UserName {
get { return UseDefaultCredentials ? DefaultCredentials.Value.UserName : userName; } get => UseDefaultCredentials ? DefaultCredentials.Value.UserName : userName;
set set
{ {
userName = value; userName = value;
...@@ -28,9 +34,12 @@ namespace Titanium.Web.Proxy.Models ...@@ -28,9 +34,12 @@ namespace Titanium.Web.Proxy.Models
} }
} }
/// <summary>
/// Password.
/// </summary>
public string Password public string Password
{ {
get { return UseDefaultCredentials ? DefaultCredentials.Value.Password : password; } get => UseDefaultCredentials ? DefaultCredentials.Value.Password : password;
set set
{ {
password = value; password = value;
...@@ -42,7 +51,13 @@ namespace Titanium.Web.Proxy.Models ...@@ -42,7 +51,13 @@ namespace Titanium.Web.Proxy.Models
} }
} }
/// <summary>
/// Host name.
/// </summary>
public string HostName { get; set; } public string HostName { get; set; }
/// <summary>
/// Port.
/// </summary>
public int Port { get; set; } public int Port { get; set; }
} }
} }
...@@ -7,6 +7,12 @@ namespace Titanium.Web.Proxy.Models ...@@ -7,6 +7,12 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class HttpHeader public class HttpHeader
{ {
/// <summary>
/// Constructor.
/// </summary>
/// <param name="name"></param>
/// <param name="value"></param>
/// <exception cref="Exception"></exception>
public HttpHeader(string name, string value) public HttpHeader(string name, string value)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
...@@ -18,7 +24,13 @@ namespace Titanium.Web.Proxy.Models ...@@ -18,7 +24,13 @@ namespace Titanium.Web.Proxy.Models
Value = value.Trim(); Value = value.Trim();
} }
/// <summary>
/// Header Name.
/// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary>
/// Header Value.
/// </summary>
public string Value { get; set; } public string Value { get; set; }
/// <summary> /// <summary>
...@@ -27,7 +39,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -27,7 +39,7 @@ namespace Titanium.Web.Proxy.Models
/// <returns></returns> /// <returns></returns>
public override string ToString() public override string ToString()
{ {
return string.Format("{0}: {1}", Name, Value); return $"{Name}: {Value}";
} }
} }
} }
\ No newline at end of file
...@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal class CertificateManager : IDisposable internal class CertificateManager : IDisposable
{ {
private CertificateMaker certEngine = null; private readonly CertificateMaker certEngine;
private bool clearCertificates { get; set; } private bool clearCertificates { get; set; }
/// <summary> /// <summary>
...@@ -21,10 +21,10 @@ namespace Titanium.Web.Proxy.Network ...@@ -21,10 +21,10 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
private readonly IDictionary<string, CachedCertificate> certificateCache; private readonly IDictionary<string, CachedCertificate> certificateCache;
private Action<Exception> exceptionFunc; private readonly Action<Exception> exceptionFunc;
internal string Issuer { get; private set; } internal string Issuer { get; }
internal string RootCertificateName { get; private set; } internal string RootCertificateName { get; }
internal X509Certificate2 rootCertificate { get; set; } internal X509Certificate2 rootCertificate { get; set; }
...@@ -35,29 +35,28 @@ namespace Titanium.Web.Proxy.Network ...@@ -35,29 +35,28 @@ namespace Titanium.Web.Proxy.Network
certEngine = new CertificateMaker(); certEngine = new CertificateMaker();
Issuer = issuer; Issuer = issuer;
RootCertificateName = rootCertificateName; RootCertificateName = rootCertificateName;
certificateCache = new ConcurrentDictionary<string, CachedCertificate>(); certificateCache = new ConcurrentDictionary<string, CachedCertificate>();
} }
internal X509Certificate2 GetRootCertificate() internal X509Certificate2 GetRootCertificate()
{ {
var fileName = Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "rootCert.pfx"); var path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
if (null == path) throw new NullReferenceException();
var fileName = Path.Combine(path, "rootCert.pfx");
if (File.Exists(fileName)) if (!File.Exists(fileName)) return null;
try
{ {
try return new X509Certificate2(fileName, string.Empty, X509KeyStorageFlags.Exportable);
{
return new X509Certificate2(fileName, string.Empty, X509KeyStorageFlags.Exportable); }
catch (Exception e)
} {
catch (Exception e) exceptionFunc(e);
{ return null;
exceptionFunc(e);
return null;
}
} }
return null;
} }
/// <summary> /// <summary>
/// Attempts to create a RootCertificate /// Attempts to create a RootCertificate
...@@ -75,7 +74,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -75,7 +74,7 @@ namespace Titanium.Web.Proxy.Network
{ {
rootCertificate = CreateCertificate(RootCertificateName, true); rootCertificate = CreateCertificate(RootCertificateName, true);
} }
catch(Exception e) catch (Exception e)
{ {
exceptionFunc(e); exceptionFunc(e);
} }
...@@ -83,38 +82,36 @@ namespace Titanium.Web.Proxy.Network ...@@ -83,38 +82,36 @@ namespace Titanium.Web.Proxy.Network
{ {
try try
{ {
var fileName = Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "rootCert.pfx"); var path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
if (null == path) throw new NullReferenceException();
var fileName = Path.Combine(path, "rootCert.pfx");
File.WriteAllBytes(fileName, rootCertificate.Export(X509ContentType.Pkcs12)); File.WriteAllBytes(fileName, rootCertificate.Export(X509ContentType.Pkcs12));
} }
catch(Exception e) catch (Exception e)
{ {
exceptionFunc(e); exceptionFunc(e);
} }
} }
return rootCertificate != null; return rootCertificate != null;
} }
/// <summary> /// <summary>
/// Create an SSL certificate /// Create an SSL certificate
/// </summary> /// </summary>
/// <param name="store"></param>
/// <param name="certificateName"></param> /// <param name="certificateName"></param>
/// <param name="isRootCertificate"></param> /// <param name="isRootCertificate"></param>
/// <returns></returns> /// <returns></returns>
internal virtual X509Certificate2 CreateCertificate(string certificateName, bool isRootCertificate) internal virtual X509Certificate2 CreateCertificate(string certificateName, bool isRootCertificate)
{ {
try
if (certificateCache.ContainsKey(certificateName))
{ {
if (certificateCache.ContainsKey(certificateName)) var cached = certificateCache[certificateName];
{ cached.LastAccess = DateTime.Now;
var cached = certificateCache[certificateName]; return cached.Certificate;
cached.LastAccess = DateTime.Now;
return cached.Certificate;
}
} }
catch
{
}
X509Certificate2 certificate = null; X509Certificate2 certificate = null;
lock (string.Intern(certificateName)) lock (string.Intern(certificateName))
{ {
...@@ -124,7 +121,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -124,7 +121,7 @@ namespace Titanium.Web.Proxy.Network
{ {
certificate = certEngine.MakeCertificate(certificateName, isRootCertificate, rootCertificate); certificate = certEngine.MakeCertificate(certificateName, isRootCertificate, rootCertificate);
} }
catch(Exception e) catch (Exception e)
{ {
exceptionFunc(e); exceptionFunc(e);
} }
...@@ -166,27 +163,20 @@ namespace Titanium.Web.Proxy.Network ...@@ -166,27 +163,20 @@ namespace Titanium.Web.Proxy.Network
clearCertificates = true; clearCertificates = true;
while (clearCertificates) while (clearCertificates)
{ {
var cutOff = DateTime.Now.AddMinutes(-1 * certificateCacheTimeOutMinutes);
try var outdated = certificateCache
{ .Where(x => x.Value.LastAccess < cutOff)
var cutOff = DateTime.Now.AddMinutes(-1 * certificateCacheTimeOutMinutes); .ToList();
var outdated = certificateCache foreach (var cache in outdated)
.Where(x => x.Value.LastAccess < cutOff) certificateCache.Remove(cache.Key);
.ToList();
foreach (var cache in outdated)
certificateCache.Remove(cache.Key);
}
finally
{
}
//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); await Task.Delay(1000 * 60);
} }
} }
internal bool TrustRootCertificate() internal bool TrustRootCertificate()
{ {
if (rootCertificate == null) if (rootCertificate == null)
...@@ -213,7 +203,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -213,7 +203,7 @@ namespace Titanium.Web.Proxy.Network
} }
return true; return true;
} }
catch catch
{ {
return false; return false;
} }
......
...@@ -47,6 +47,9 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -47,6 +47,9 @@ namespace Titanium.Web.Proxy.Network.Tcp
LastAccess = DateTime.Now; LastAccess = DateTime.Now;
} }
/// <summary>
/// Dispose.
/// </summary>
public void Dispose() public void Dispose()
{ {
Stream.Close(); Stream.Close();
......
...@@ -19,14 +19,12 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -19,14 +19,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal class TcpConnectionFactory internal class TcpConnectionFactory
{ {
/// <summary> /// <summary>
/// Creates a TCP connection to server /// Creates a TCP connection to server
/// </summary> /// </summary>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
/// <param name="connectionTimeOutSeconds"></param> /// <param name="connectionTimeOutSeconds"></param>
/// <param name="remoteHostName"></param> /// <param name="remoteHostName"></param>
/// <param name="httpCmd"></param>
/// <param name="httpVersion"></param> /// <param name="httpVersion"></param>
/// <param name="isHttps"></param> /// <param name="isHttps"></param>
/// <param name="remotePort"></param> /// <param name="remotePort"></param>
...@@ -69,7 +67,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -69,7 +67,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
if (!string.IsNullOrEmpty(externalHttpsProxy.UserName) && externalHttpsProxy.Password != null) if (!string.IsNullOrEmpty(externalHttpsProxy.UserName) && externalHttpsProxy.Password != null)
{ {
await writer.WriteLineAsync("Proxy-Connection: keep-alive"); await writer.WriteLineAsync("Proxy-Connection: keep-alive");
await writer.WriteLineAsync("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(externalHttpsProxy.UserName + ":" + externalHttpsProxy.Password))); await writer.WriteLineAsync("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(externalHttpsProxy.UserName + ":" + externalHttpsProxy.Password)));
} }
await writer.WriteLineAsync(); await writer.WriteLineAsync();
await writer.FlushAsync(); await writer.FlushAsync();
...@@ -81,7 +79,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -81,7 +79,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
var result = await reader.ReadLineAsync(); var result = await reader.ReadLineAsync();
if (!new string[] { "200 OK", "connection established" }.Any(s => result.ToLower().Contains(s.ToLower()))) if (!new[] { "200 OK", "connection established" }.Any(s => result.ToLower().Contains(s.ToLower())))
{ {
throw new Exception("Upstream proxy failed to create a secure tunnel"); throw new Exception("Upstream proxy failed to create a secure tunnel");
} }
......
...@@ -29,16 +29,16 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -29,16 +29,16 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Gets the local end point. /// Gets the local end point.
/// </summary> /// </summary>
public IPEndPoint LocalEndPoint { get; private set; } public IPEndPoint LocalEndPoint { get; }
/// <summary> /// <summary>
/// Gets the remote end point. /// Gets the remote end point.
/// </summary> /// </summary>
public IPEndPoint RemoteEndPoint { get; private set; } public IPEndPoint RemoteEndPoint { get; }
/// <summary> /// <summary>
/// Gets the process identifier. /// Gets the process identifier.
/// </summary> /// </summary>
public int ProcessId { get; private set; } public int ProcessId { get; }
} }
} }
\ No newline at end of file
...@@ -6,7 +6,9 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -6,7 +6,9 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Represents collection of TcpRows /// Represents collection of TcpRows
/// </summary> /// </summary>
/// <seealso cref="System.Collections.Generic.IEnumerable{Proxy.Tcp.TcpRow}" /> /// <seealso>
/// <cref>System.Collections.Generic.IEnumerable{Proxy.Tcp.TcpRow}</cref>
/// </seealso>
internal class TcpTable : IEnumerable<TcpRow> internal class TcpTable : IEnumerable<TcpRow>
{ {
private readonly IEnumerable<TcpRow> tcpRows; private readonly IEnumerable<TcpRow> tcpRows;
......
...@@ -24,58 +24,78 @@ namespace Titanium.Web.Proxy ...@@ -24,58 +24,78 @@ namespace Titanium.Web.Proxy
try try
{ {
if (!httpHeaders.Where(t => t.Name == "Proxy-Authorization").Any()) if (httpHeaders.All(t => t.Name != "Proxy-Authorization"))
{ {
await WriteResponseStatus(new Version(1, 1), "407", await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Required", clientStreamWriter); "Proxy Authentication Required", clientStreamWriter);
var response = new Response(); var response = new Response
response.ResponseHeaders = new Dictionary<string, HttpHeader>(); {
response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")); ResponseHeaders = new Dictionary<string, HttpHeader>
response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close")); {
{
"Proxy-Authenticate",
new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
else var header = httpHeaders.FirstOrDefault(t => t.Name == "Proxy-Authorization");
if (null == header) throw new NullReferenceException();
var headerValue = header.Value.Trim();
if (!headerValue.ToLower().StartsWith("basic"))
{ {
var headerValue = httpHeaders.Where(t => t.Name == "Proxy-Authorization").FirstOrDefault().Value.Trim(); //Return not authorized
if (!headerValue.ToLower().StartsWith("basic")) await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Invalid", clientStreamWriter);
var response = new Response
{ {
//Return not authorized ResponseHeaders = new Dictionary<string, HttpHeader>
await WriteResponseStatus(new Version(1, 1), "407", {
"Proxy Authentication Invalid", clientStreamWriter); {
var response = new Response(); "Proxy-Authenticate",
response.ResponseHeaders = new Dictionary<string, HttpHeader>(); new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")); },
response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close")); {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
await WriteResponseHeaders(clientStreamWriter, response); }
};
await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
return false; return false;
} }
headerValue = headerValue.Substring(5).Trim(); headerValue = headerValue.Substring(5).Trim();
var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue)); var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue));
if (decoded.Contains(":") == false) if (decoded.Contains(":") == false)
{
//Return not authorized
await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Invalid", clientStreamWriter);
var response = new Response
{ {
//Return not authorized ResponseHeaders = new Dictionary<string, HttpHeader>
await WriteResponseStatus(new Version(1, 1), "407", {
"Proxy Authentication Invalid", clientStreamWriter); {
var response = new Response(); "Proxy-Authenticate",
response.ResponseHeaders = new Dictionary<string, HttpHeader>(); new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")
response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")); },
response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close")); {"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
await WriteResponseHeaders(clientStreamWriter, response); }
};
await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
return false; return false;
}
var username = decoded.Substring(0, decoded.IndexOf(':'));
var password = decoded.Substring(decoded.IndexOf(':') + 1);
return await AuthenticateUserFunc(username, password).ConfigureAwait(false);
} }
var username = decoded.Substring(0, decoded.IndexOf(':'));
var password = decoded.Substring(decoded.IndexOf(':') + 1);
return await AuthenticateUserFunc(username, password).ConfigureAwait(false);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -83,10 +103,14 @@ namespace Titanium.Web.Proxy ...@@ -83,10 +103,14 @@ namespace Titanium.Web.Proxy
//Return not authorized //Return not authorized
await WriteResponseStatus(new Version(1, 1), "407", await WriteResponseStatus(new Version(1, 1), "407",
"Proxy Authentication Invalid", clientStreamWriter); "Proxy Authentication Invalid", clientStreamWriter);
var response = new Response(); var response = new Response
response.ResponseHeaders = new Dictionary<string, HttpHeader>(); {
response.ResponseHeaders.Add("Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")); ResponseHeaders = new Dictionary<string, HttpHeader>
response.ResponseHeaders.Add("Proxy-Connection", new HttpHeader("Proxy-Connection", "close")); {
{"Proxy-Authenticate", new HttpHeader("Proxy-Authenticate", "Basic realm=\"TitaniumProxy\"")},
{"Proxy-Connection", new HttpHeader("Proxy-Connection", "close")}
}
};
await WriteResponseHeaders(clientStreamWriter, response); await WriteResponseHeaders(clientStreamWriter, response);
await clientStreamWriter.WriteLineAsync(); await clientStreamWriter.WriteLineAsync();
......
...@@ -47,14 +47,16 @@ namespace Titanium.Web.Proxy ...@@ -47,14 +47,16 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// A object that creates tcp connection to server /// A object that creates tcp connection to server
/// </summary> /// </summary>
private TcpConnectionFactory tcpConnectionFactory { get; set; } private TcpConnectionFactory tcpConnectionFactory { get; }
/// <summary> /// <summary>
/// Manage system proxy settings /// Manage system proxy settings
/// </summary> /// </summary>
private SystemProxyManager systemProxySettingsManager { get; set; } private SystemProxyManager systemProxySettingsManager { get; }
#if !DEBUG
private FireFoxProxySettingsManager firefoxProxySettingsManager { get; set; } private FireFoxProxySettingsManager firefoxProxySettingsManager { get; set; }
#endif
/// <summary> /// <summary>
/// Buffer size used throughout this proxy /// Buffer size used throughout this proxy
...@@ -138,14 +140,8 @@ namespace Titanium.Web.Proxy ...@@ -138,14 +140,8 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public Action<Exception> ExceptionFunc public Action<Exception> ExceptionFunc
{ {
get get => exceptionFunc ?? defaultExceptionFunc.Value;
{ set => exceptionFunc = value;
return exceptionFunc ?? defaultExceptionFunc.Value;
}
set
{
exceptionFunc = value;
}
} }
/// <summary> /// <summary>
...@@ -172,6 +168,7 @@ namespace Titanium.Web.Proxy ...@@ -172,6 +168,7 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTPS requests /// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTPS requests
/// return the ExternalProxy object with valid credentials /// return the ExternalProxy object with valid credentials
/// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamHttpsProxyFunc public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamHttpsProxyFunc
{ {
get; get;
...@@ -203,6 +200,11 @@ namespace Titanium.Web.Proxy ...@@ -203,6 +200,11 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public ProxyServer() : this(null, null) { } public ProxyServer() : this(null, null) { }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="rootCertificateName">Name of root certificate.</param>
/// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param>
public ProxyServer(string rootCertificateName, string rootCertificateIssuerName) public ProxyServer(string rootCertificateName, string rootCertificateIssuerName)
{ {
RootCertificateName = rootCertificateName; RootCertificateName = rootCertificateName;
...@@ -214,8 +216,9 @@ namespace Titanium.Web.Proxy ...@@ -214,8 +216,9 @@ namespace Titanium.Web.Proxy
ProxyEndPoints = new List<ProxyEndPoint>(); ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory(); tcpConnectionFactory = new TcpConnectionFactory();
systemProxySettingsManager = new SystemProxyManager(); systemProxySettingsManager = new SystemProxyManager();
firefoxProxySettingsManager = new FireFoxProxySettingsManager(); #if !DEBUG
new FireFoxProxySettingsManager();
#endif
RootCertificateName = RootCertificateName ?? "Titanium Root Certificate Authority"; RootCertificateName = RootCertificateName ?? "Titanium Root Certificate Authority";
RootCertificateIssuerName = RootCertificateIssuerName ?? "Titanium"; RootCertificateIssuerName = RootCertificateIssuerName ?? "Titanium";
} }
...@@ -277,7 +280,7 @@ namespace Titanium.Web.Proxy ...@@ -277,7 +280,7 @@ namespace Titanium.Web.Proxy
#if !DEBUG #if !DEBUG
firefoxProxySettingsManager.AddFirefox(); firefoxProxySettingsManager.AddFirefox();
#endif #endif
Console.WriteLine("Set endpoint at Ip {1} and port: {2} as System HTTP Proxy", endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port); Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTP Proxy", endPoint.IpAddress, endPoint.Port);
} }
...@@ -313,7 +316,7 @@ namespace Titanium.Web.Proxy ...@@ -313,7 +316,7 @@ namespace Titanium.Web.Proxy
#if !DEBUG #if !DEBUG
firefoxProxySettingsManager.AddFirefox(); firefoxProxySettingsManager.AddFirefox();
#endif #endif
Console.WriteLine("Set endpoint at Ip {1} and port: {2} as System HTTPS Proxy", endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port); Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy", endPoint.IpAddress, endPoint.Port);
} }
/// <summary> /// <summary>
...@@ -461,6 +464,7 @@ namespace Titanium.Web.Proxy ...@@ -461,6 +464,7 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint"></param> /// <param name="endPoint"></param>
private void ValidateEndPointAsSystemProxy(ExplicitProxyEndPoint endPoint) private void ValidateEndPointAsSystemProxy(ExplicitProxyEndPoint endPoint)
{ {
if (endPoint == null) throw new ArgumentNullException(nameof(endPoint));
if (ProxyEndPoints.Contains(endPoint) == false) if (ProxyEndPoints.Contains(endPoint) == false)
{ {
throw new Exception("Cannot set endPoints not added to proxy as system proxy"); throw new Exception("Cannot set endPoints not added to proxy as system proxy");
...@@ -542,6 +546,9 @@ namespace Titanium.Web.Proxy ...@@ -542,6 +546,9 @@ namespace Titanium.Web.Proxy
endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint); endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
} }
/// <summary>
/// Dispose Proxy.
/// </summary>
public void Dispose() public void Dispose()
{ {
if (proxyRunning) if (proxyRunning)
...@@ -551,5 +558,45 @@ namespace Titanium.Web.Proxy ...@@ -551,5 +558,45 @@ namespace Titanium.Web.Proxy
certificateCacheManager?.Dispose(); certificateCacheManager?.Dispose();
} }
/// <summary>
/// Invocator for BeforeRequest event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void OnBeforeRequest(object sender, SessionEventArgs e)
{
BeforeRequest?.Invoke(sender, e);
}
/// <summary>
/// Invocator for BeforeResponse event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <returns></returns>
protected virtual void OnBeforeResponse(object sender, SessionEventArgs e)
{
BeforeResponse?.Invoke(sender, e);
}
/// <summary>
/// Invocator for ServerCertificateValidationCallback event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void OnServerCertificateValidationCallback(object sender, CertificateValidationEventArgs e)
{
ServerCertificateValidationCallback?.Invoke(sender, e);
}
/// <summary>
/// Invocator for ClientCertifcateSelectionCallback event.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void OnClientCertificateSelectionCallback(object sender, CertificateSelectionEventArgs e)
{
ClientCertificateSelectionCallback?.Invoke(sender, e);
}
} }
} }
\ No newline at end of file
This diff is collapsed.
...@@ -17,7 +17,11 @@ namespace Titanium.Web.Proxy ...@@ -17,7 +17,11 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
partial class ProxyServer partial class ProxyServer
{ {
//Called asynchronously when a request was successfully and we received the response /// <summary>
/// Called asynchronously when a request was successfully and we received the response
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public async Task HandleHttpSessionResponse(SessionEventArgs args) public async Task HandleHttpSessionResponse(SessionEventArgs args)
{ {
//read response & headers from server //read response & headers from server
...@@ -156,14 +160,14 @@ namespace Titanium.Web.Proxy ...@@ -156,14 +160,14 @@ namespace Titanium.Web.Proxy
private async Task WriteResponseStatus(Version version, string code, string description, private async Task WriteResponseStatus(Version version, string code, string description,
StreamWriter responseWriter) StreamWriter responseWriter)
{ {
await responseWriter.WriteLineAsync(string.Format("HTTP/{0}.{1} {2} {3}", version.Major, version.Minor, code, description)); await responseWriter.WriteLineAsync($"HTTP/{version.Major}.{version.Minor} {code} {description}");
} }
/// <summary> /// <summary>
/// Write response headers to client /// Write response headers to client
/// </summary> /// </summary>
/// <param name="responseWriter"></param> /// <param name="responseWriter"></param>
/// <param name="headers"></param> /// <param name="response"></param>
/// <returns></returns> /// <returns></returns>
private async Task WriteResponseHeaders(StreamWriter responseWriter, Response response) private async Task WriteResponseHeaders(StreamWriter responseWriter, Response response)
{ {
...@@ -220,7 +224,6 @@ namespace Titanium.Web.Proxy ...@@ -220,7 +224,6 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Handle dispose of a client/server session /// Handle dispose of a client/server session
/// </summary> /// </summary>
/// <param name="tcpClient"></param>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param> /// <param name="clientStreamWriter"></param>
...@@ -235,21 +238,13 @@ namespace Titanium.Web.Proxy ...@@ -235,21 +238,13 @@ namespace Titanium.Web.Proxy
clientStream.Dispose(); clientStream.Dispose();
} }
if (args != null) args?.Dispose();
{
args.Dispose();
}
if (clientStreamReader != null) clientStreamReader?.Dispose();
{
clientStreamReader.Dispose();
}
if (clientStreamWriter != null) if (clientStreamWriter == null) return;
{ clientStreamWriter.Close();
clientStreamWriter.Close(); clientStreamWriter.Dispose();
clientStreamWriter.Dispose();
}
} }
} }
} }
\ No newline at end of file
using System; using System.Text;
using System.Text;
namespace Titanium.Web.Proxy.Shared namespace Titanium.Web.Proxy.Shared
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment