Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

beta #679

Merged
merged 4 commits into from
Nov 24, 2019
Merged

beta #679

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public ProxyTestController()
proxyServer.ForwardToUpstreamGateway = true;
proxyServer.CertificateManager.SaveFakeCertificates = true;

// this is just to show the functionality, provided implementations use junk value
//proxyServer.GetCustomUpStreamProxyFunc = onGetCustomUpStreamProxyFunc;
//proxyServer.CustomUpStreamProxyFailureFunc = onCustomUpStreamProxyFailureFunc;

// optionally set the Certificate Engine
// Under Mono or Non-Windows runtimes only BouncyCastle will be supported
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
Expand Down Expand Up @@ -116,6 +120,18 @@ public void Stop()
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
}

private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
{
// this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake", UseDefaultCredentials = false };
}

private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
{
// this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2", UseDefaultCredentials = false };
}

private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
string hostname = e.HttpClient.Request.RequestUri.Host;
Expand Down
2 changes: 2 additions & 0 deletions examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" />
<GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" />
<GridViewColumn Header="ClientEndPoint" DisplayMemberBinding="{Binding ClientEndPoint}" />
<GridViewColumn Header="ClientConnectionId" DisplayMemberBinding="{Binding ClientConnectionId}" />
<GridViewColumn Header="ServerConnectionId" DisplayMemberBinding="{Binding ServerConnectionId}" />
</GridView>
</ListView.View>
</ListView>
Expand Down
41 changes: 32 additions & 9 deletions examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,15 @@ await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.HttpClient, out var item))
{
item.Update();
item.Update(e);
}
});
}

private async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e)
{
//if (e.HttpClient.Request.HttpVersion.Major != 2) return;

SessionListItem item = null;
await Dispatcher.InvokeAsync(() => { item = addSession(e); });

Expand All @@ -175,7 +177,7 @@ await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.HttpClient, out item))
{
item.Update();
item.Update(e);
}
});

Expand All @@ -190,7 +192,7 @@ await Dispatcher.InvokeAsync(() =>
e.HttpClient.Response.KeepBody = true;
await e.GetResponseBody();

await Dispatcher.InvokeAsync(() => { item.Update(); });
await Dispatcher.InvokeAsync(() => { item.Update(e); });
if (item == SelectedSession)
{
await Dispatcher.InvokeAsync(selectedSessionChanged);
Expand Down Expand Up @@ -225,6 +227,8 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
var item = new SessionListItem
{
Number = lastSessionNumber,
ClientConnectionId = e.ClientConnectionId,
ServerConnectionId = e.ServerConnectionId,
HttpClient = e.HttpClient,
ClientEndPoint = e.ClientEndPoint,
IsTunnelConnect = isTunnelConnect
Expand All @@ -236,14 +240,16 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
var connectRequest = session.HttpClient.ConnectRequest;
var tunnelType = connectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}

li.ReceivedDataCount += args.Count;

//if (tunnelType == TunnelType.Http2)
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_received",
args.Buffer, args.Offset, args.Count);
}
Expand All @@ -254,15 +260,17 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
var connectRequest = session.HttpClient.ConnectRequest;
var tunnelType = connectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}

li.SentDataCount += args.Count;

AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
//if (tunnelType == TunnelType.Http2)
AppendTransferLog( session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
args.Buffer, args.Offset, args.Count);
}
};
Expand All @@ -272,18 +280,22 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
te.DecryptedDataReceived += (sender, args) =>
{
var session = (SessionEventArgsBase)sender;
//var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
//if (tunnelType == TunnelType.Http2)
AppendTransferLog(session.GetHashCode() + "_decrypted_received", args.Buffer, args.Offset,
args.Count);
};

te.DecryptedDataSent += (sender, args) =>
{
var session = (SessionEventArgsBase)sender;
//var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
//if (tunnelType == TunnelType.Http2)
AppendTransferLog(session.GetHashCode() + "_decrypted_sent", args.Buffer, args.Offset, args.Count);
};
}

item.Update();
item.Update(e);
return item;
}

Expand Down Expand Up @@ -362,9 +374,15 @@ private void selectedSessionChanged()

//string hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
var sb = new StringBuilder();
sb.AppendLine("URI: " + request.RequestUri);
sb.Append(request.HeaderText);
sb.Append(request.Encoding.GetString(data));
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
if (truncated)
{
sb.AppendLine();
sb.Append($"Data is truncated after {truncateLimit} bytes");
}

sb.Append((request as ConnectRequest)?.ClientHelloInfo);
TextBoxRequest.Text = sb.ToString();

Expand All @@ -381,7 +399,12 @@ private void selectedSessionChanged()
sb = new StringBuilder();
sb.Append(response.HeaderText);
sb.Append(response.Encoding.GetString(data));
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
if (truncated)
{
sb.AppendLine();
sb.Append($"Data is truncated after {truncateLimit} bytes");
}

sb.Append((response as ConnectResponse)?.ServerHelloInfo);
if (SelectedSession.Exception != null)
{
Expand Down
19 changes: 18 additions & 1 deletion examples/Titanium.Web.Proxy.Examples.Wpf/SessionListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Net;
using System.Runtime.CompilerServices;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Examples.Wpf.Annotations;
using Titanium.Web.Proxy.Http;

Expand All @@ -18,9 +19,23 @@ public class SessionListItem : INotifyPropertyChanged
private long sentDataCount;
private string statusCode;
private string url;
private Guid clientConnectionId;
private Guid serverConnectionId;

public int Number { get; set; }

public Guid ClientConnectionId
{
get => clientConnectionId;
set => SetField(ref clientConnectionId, value);
}

public Guid ServerConnectionId
{
get => serverConnectionId;
set => SetField(ref serverConnectionId, value);
}

public HttpWebClient HttpClient { get; set; }

public IPEndPoint ClientEndPoint { get; set; }
Expand Down Expand Up @@ -123,13 +138,15 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public void Update()
public void Update(SessionEventArgsBase args)
{
var request = HttpClient.Request;
var response = HttpClient.Response;
int statusCode = response?.StatusCode ?? 0;
StatusCode = statusCode == 0 ? "-" : statusCode.ToString();
Protocol = request.RequestUri.Scheme;
ClientConnectionId = args.ClientConnectionId;
ServerConnectionId = args.ServerConnectionId;

if (IsTunnelConnect)
{
Expand Down
67 changes: 10 additions & 57 deletions src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ public bool ReRequest
/// </summary>
public event EventHandler<MultipartRequestPartSentEventArgs>? MultipartRequestPartSent;

private HttpStream getStream(bool isRequest)
{
return isRequest ? (HttpStream)ClientStream : HttpClient.Connection.Stream;
}

/// <summary>
/// Read request body content as bytes[] for current session
/// </summary>
Expand Down Expand Up @@ -194,15 +189,15 @@ private async Task readResponseBodyAsync(CancellationToken cancellationToken)
private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken)
{
using var bodyStream = new MemoryStream();
using var http = new HttpStream(bodyStream, BufferPool);
using var writer = new HttpStream(bodyStream, BufferPool);

if (isRequest)
{
await CopyRequestBodyAsync(http, TransformationMode.Uncompress, cancellationToken);
await CopyRequestBodyAsync(writer, TransformationMode.Uncompress, cancellationToken);
}
else
{
await CopyResponseBodyAsync(http, TransformationMode.Uncompress, cancellationToken);
await copyResponseBodyAsync(writer, TransformationMode.Uncompress, cancellationToken);
}

return bodyStream.ToArray();
Expand All @@ -223,9 +218,9 @@ internal async Task SyphonOutBodyAsync(bool isRequest, CancellationToken cancell
return;
}

using var bodyStream = new MemoryStream();
using var http = new HttpStream(bodyStream, BufferPool);
await copyBodyAsync(isRequest, true, http, TransformationMode.None, null, cancellationToken);
var reader = isRequest ? (HttpStream)ClientStream : HttpClient.Connection.Stream;

await reader.CopyBodyAsync(requestResponse, true, new NullWriter(), TransformationMode.None, null, cancellationToken);
}

/// <summary>
Expand All @@ -235,13 +230,13 @@ internal async Task SyphonOutBodyAsync(bool isRequest, CancellationToken cancell
internal async Task CopyRequestBodyAsync(IHttpStreamWriter writer, TransformationMode transformation, CancellationToken cancellationToken)
{
var request = HttpClient.Request;
var reader = ClientStream;

long contentLength = request.ContentLength;

// send the request body bytes to server
if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData)
{
var reader = getStream(true);
var boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);

using (var copyStream = new CopyStream(reader, writer, BufferPool))
Expand All @@ -267,54 +262,13 @@ internal async Task CopyRequestBodyAsync(IHttpStreamWriter writer, Transformatio
}
else
{
await copyBodyAsync(true, false, writer, transformation, OnDataSent, cancellationToken);
await reader.CopyBodyAsync(request, false, writer, transformation, OnDataSent, cancellationToken);
}
}

internal async Task CopyResponseBodyAsync(IHttpStreamWriter writer, TransformationMode transformation, CancellationToken cancellationToken)
{
await copyBodyAsync(false, false, writer, transformation, OnDataReceived, cancellationToken);
}

private async Task copyBodyAsync(bool isRequest, bool useOriginalHeaderValues, IHttpStreamWriter writer, TransformationMode transformation, Action<byte[], int, int>? onCopy, CancellationToken cancellationToken)
private async Task copyResponseBodyAsync(IHttpStreamWriter writer, TransformationMode transformation, CancellationToken cancellationToken)
{
var stream = getStream(isRequest);

var requestResponse = isRequest ? (RequestResponseBase)HttpClient.Request : HttpClient.Response;

bool isChunked = useOriginalHeaderValues? requestResponse.OriginalIsChunked : requestResponse.IsChunked;
long contentLength = useOriginalHeaderValues ? requestResponse.OriginalContentLength : requestResponse.ContentLength;

if (transformation == TransformationMode.None)
{
await writer.CopyBodyAsync(stream, isChunked, contentLength, onCopy, cancellationToken);
return;
}

LimitedStream limitedStream;
Stream? decompressStream = null;

string? contentEncoding = useOriginalHeaderValues ? requestResponse.OriginalContentEncoding : requestResponse.ContentEncoding;

Stream s = limitedStream = new LimitedStream(stream, BufferPool, isChunked, contentLength);

if (transformation == TransformationMode.Uncompress && contentEncoding != null)
{
s = decompressStream = DecompressionFactory.Create(CompressionUtil.CompressionNameToEnum(contentEncoding), s);
}

try
{
var http = new HttpStream(s, BufferPool, true);
await writer.CopyBodyAsync(http, false, -1, onCopy, cancellationToken);
}
finally
{
decompressStream?.Dispose();

await limitedStream.Finish();
limitedStream.Dispose();
}
await HttpClient.Connection.Stream.CopyBodyAsync(HttpClient.Response, false, writer, transformation, OnDataReceived, cancellationToken);
}

/// <summary>
Expand Down Expand Up @@ -638,7 +592,6 @@ public void Respond(Response response, bool closeServerConnection = false)
HttpClient.Response = response;
HttpClient.Response.Locked = true;
}

}

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ public abstract class SessionEventArgsBase : EventArgs, IDisposable

internal HttpClientStream ClientStream { get; }

public Guid ClientConnectionId => ClientConnection.Id;

public Guid ServerConnectionId => HttpClient.HasConnection ? ServerConnection.Id : Guid.Empty;

protected readonly IBufferPool BufferPool;
protected readonly ExceptionHandler ExceptionFunc;
private bool enableWinAuth;
Expand Down
Loading