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

Commit 931d59c

Browse files
authored
Merge pull request #688 from justcoding121/master
stable
2 parents 886752d + dd0a19a commit 931d59c

40 files changed

+686
-381
lines changed

examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ public ProxyTestController()
4242
proxyServer.ForwardToUpstreamGateway = true;
4343
proxyServer.CertificateManager.SaveFakeCertificates = true;
4444

45+
// this is just to show the functionality, provided implementations use junk value
46+
//proxyServer.GetCustomUpStreamProxyFunc = onGetCustomUpStreamProxyFunc;
47+
//proxyServer.CustomUpStreamProxyFailureFunc = onCustomUpStreamProxyFailureFunc;
48+
4549
// optionally set the Certificate Engine
4650
// Under Mono or Non-Windows runtimes only BouncyCastle will be supported
4751
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
@@ -116,6 +120,18 @@ public void Stop()
116120
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
117121
}
118122

123+
private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
124+
{
125+
// this is just to show the functionality, provided values are junk
126+
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake", UseDefaultCredentials = false };
127+
}
128+
129+
private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
130+
{
131+
// this is just to show the functionality, provided values are junk
132+
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2", UseDefaultCredentials = false };
133+
}
134+
119135
private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
120136
{
121137
string hostname = e.HttpClient.Request.RequestUri.Host;
@@ -135,7 +151,7 @@ private Task onBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEv
135151
return Task.FromResult(false);
136152
}
137153

138-
// intecept & cancel redirect or update requests
154+
// intercept & cancel redirect or update requests
139155
private async Task onRequest(object sender, SessionEventArgs e)
140156
{
141157
await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);

examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
<GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" />
3333
<GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" />
3434
<GridViewColumn Header="ClientEndPoint" DisplayMemberBinding="{Binding ClientEndPoint}" />
35+
<GridViewColumn Header="ClientConnectionId" DisplayMemberBinding="{Binding ClientConnectionId}" />
36+
<GridViewColumn Header="ServerConnectionId" DisplayMemberBinding="{Binding ServerConnectionId}" />
3537
</GridView>
3638
</ListView.View>
3739
</ListView>

examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,15 @@ await Dispatcher.InvokeAsync(() =>
146146
{
147147
if (sessionDictionary.TryGetValue(e.HttpClient, out var item))
148148
{
149-
item.Update();
149+
item.Update(e);
150150
}
151151
});
152152
}
153153

154154
private async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e)
155155
{
156+
//if (e.HttpClient.Request.HttpVersion.Major != 2) return;
157+
156158
SessionListItem item = null;
157159
await Dispatcher.InvokeAsync(() => { item = addSession(e); });
158160

@@ -175,7 +177,7 @@ await Dispatcher.InvokeAsync(() =>
175177
{
176178
if (sessionDictionary.TryGetValue(e.HttpClient, out item))
177179
{
178-
item.Update();
180+
item.Update(e);
179181
}
180182
});
181183

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

193-
await Dispatcher.InvokeAsync(() => { item.Update(); });
195+
await Dispatcher.InvokeAsync(() => { item.Update(e); });
194196
if (item == SelectedSession)
195197
{
196198
await Dispatcher.InvokeAsync(selectedSessionChanged);
@@ -225,6 +227,8 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
225227
var item = new SessionListItem
226228
{
227229
Number = lastSessionNumber,
230+
ClientConnectionId = e.ClientConnectionId,
231+
ServerConnectionId = e.ServerConnectionId,
228232
HttpClient = e.HttpClient,
229233
ClientEndPoint = e.ClientEndPoint,
230234
IsTunnelConnect = isTunnelConnect
@@ -236,14 +240,16 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
236240
var session = (SessionEventArgsBase)sender;
237241
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
238242
{
239-
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
243+
var connectRequest = session.HttpClient.ConnectRequest;
244+
var tunnelType = connectRequest?.TunnelType ?? TunnelType.Unknown;
240245
if (tunnelType != TunnelType.Unknown)
241246
{
242247
li.Protocol = TunnelTypeToString(tunnelType);
243248
}
244249

245250
li.ReceivedDataCount += args.Count;
246251

252+
//if (tunnelType == TunnelType.Http2)
247253
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_received",
248254
args.Buffer, args.Offset, args.Count);
249255
}
@@ -254,15 +260,17 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
254260
var session = (SessionEventArgsBase)sender;
255261
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
256262
{
257-
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
263+
var connectRequest = session.HttpClient.ConnectRequest;
264+
var tunnelType = connectRequest?.TunnelType ?? TunnelType.Unknown;
258265
if (tunnelType != TunnelType.Unknown)
259266
{
260267
li.Protocol = TunnelTypeToString(tunnelType);
261268
}
262269

263270
li.SentDataCount += args.Count;
264271

265-
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
272+
//if (tunnelType == TunnelType.Http2)
273+
AppendTransferLog( session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
266274
args.Buffer, args.Offset, args.Count);
267275
}
268276
};
@@ -272,18 +280,22 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
272280
te.DecryptedDataReceived += (sender, args) =>
273281
{
274282
var session = (SessionEventArgsBase)sender;
283+
//var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
284+
//if (tunnelType == TunnelType.Http2)
275285
AppendTransferLog(session.GetHashCode() + "_decrypted_received", args.Buffer, args.Offset,
276286
args.Count);
277287
};
278288

279289
te.DecryptedDataSent += (sender, args) =>
280290
{
281291
var session = (SessionEventArgsBase)sender;
292+
//var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
293+
//if (tunnelType == TunnelType.Http2)
282294
AppendTransferLog(session.GetHashCode() + "_decrypted_sent", args.Buffer, args.Offset, args.Count);
283295
};
284296
}
285297

286-
item.Update();
298+
item.Update(e);
287299
return item;
288300
}
289301

@@ -362,9 +374,15 @@ private void selectedSessionChanged()
362374

363375
//string hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
364376
var sb = new StringBuilder();
377+
sb.AppendLine("URI: " + request.RequestUri);
365378
sb.Append(request.HeaderText);
366379
sb.Append(request.Encoding.GetString(data));
367-
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
380+
if (truncated)
381+
{
382+
sb.AppendLine();
383+
sb.Append($"Data is truncated after {truncateLimit} bytes");
384+
}
385+
368386
sb.Append((request as ConnectRequest)?.ClientHelloInfo);
369387
TextBoxRequest.Text = sb.ToString();
370388

@@ -381,7 +399,12 @@ private void selectedSessionChanged()
381399
sb = new StringBuilder();
382400
sb.Append(response.HeaderText);
383401
sb.Append(response.Encoding.GetString(data));
384-
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
402+
if (truncated)
403+
{
404+
sb.AppendLine();
405+
sb.Append($"Data is truncated after {truncateLimit} bytes");
406+
}
407+
385408
sb.Append((response as ConnectResponse)?.ServerHelloInfo);
386409
if (SelectedSession.Exception != null)
387410
{

examples/Titanium.Web.Proxy.Examples.Wpf/SessionListItem.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.ComponentModel;
33
using System.Net;
44
using System.Runtime.CompilerServices;
5+
using Titanium.Web.Proxy.EventArguments;
56
using Titanium.Web.Proxy.Examples.Wpf.Annotations;
67
using Titanium.Web.Proxy.Http;
78

@@ -18,9 +19,23 @@ public class SessionListItem : INotifyPropertyChanged
1819
private long sentDataCount;
1920
private string statusCode;
2021
private string url;
22+
private Guid clientConnectionId;
23+
private Guid serverConnectionId;
2124

2225
public int Number { get; set; }
2326

27+
public Guid ClientConnectionId
28+
{
29+
get => clientConnectionId;
30+
set => SetField(ref clientConnectionId, value);
31+
}
32+
33+
public Guid ServerConnectionId
34+
{
35+
get => serverConnectionId;
36+
set => SetField(ref serverConnectionId, value);
37+
}
38+
2439
public HttpWebClient HttpClient { get; set; }
2540

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

126-
public void Update()
141+
public void Update(SessionEventArgsBase args)
127142
{
128143
var request = HttpClient.Request;
129144
var response = HttpClient.Response;
130145
int statusCode = response?.StatusCode ?? 0;
131146
StatusCode = statusCode == 0 ? "-" : statusCode.ToString();
132147
Protocol = request.RequestUri.Scheme;
148+
ClientConnectionId = args.ClientConnectionId;
149+
ServerConnectionId = args.ServerConnectionId;
133150

134151
if (IsTunnelConnect)
135152
{

src/Titanium.Web.Proxy/EventArguments/LimitedStream.cs

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
using System;
22
using System.Globalization;
33
using System.IO;
4+
using System.Threading;
45
using System.Threading.Tasks;
56
using Titanium.Web.Proxy.Exceptions;
6-
using Titanium.Web.Proxy.Helpers;
77
using Titanium.Web.Proxy.StreamExtended.BufferPool;
88
using Titanium.Web.Proxy.StreamExtended.Network;
99

@@ -51,11 +51,22 @@ private void getNextChunk()
5151
{
5252
// read the chunk trail of the previous chunk
5353
string? s = baseReader.ReadLineAsync().Result;
54+
if (s == null)
55+
{
56+
bytesRemaining = -1;
57+
return;
58+
}
5459
}
5560

5661
readChunkTrail = true;
5762

58-
string? chunkHead = baseReader.ReadLineAsync().Result!;
63+
string? chunkHead = baseReader.ReadLineAsync().Result;
64+
if (chunkHead == null)
65+
{
66+
bytesRemaining = -1;
67+
return;
68+
}
69+
5970
int idx = chunkHead.IndexOf(";", StringComparison.Ordinal);
6071
if (idx >= 0)
6172
{
@@ -80,6 +91,50 @@ private void getNextChunk()
8091
}
8192
}
8293

94+
private async Task getNextChunkAsync()
95+
{
96+
if (readChunkTrail)
97+
{
98+
// read the chunk trail of the previous chunk
99+
string? s = await baseReader.ReadLineAsync();
100+
if (s == null)
101+
{
102+
bytesRemaining = -1;
103+
return;
104+
}
105+
}
106+
107+
readChunkTrail = true;
108+
109+
string? chunkHead = await baseReader.ReadLineAsync();
110+
if (chunkHead == null)
111+
{
112+
bytesRemaining = -1;
113+
return;
114+
}
115+
116+
int idx = chunkHead.IndexOf(";", StringComparison.Ordinal);
117+
if (idx >= 0)
118+
{
119+
chunkHead = chunkHead.Substring(0, idx);
120+
}
121+
122+
if (!int.TryParse(chunkHead, NumberStyles.HexNumber, null, out int chunkSize))
123+
{
124+
throw new ProxyHttpException($"Invalid chunk length: '{chunkHead}'", null, null);
125+
}
126+
127+
bytesRemaining = chunkSize;
128+
129+
if (chunkSize == 0)
130+
{
131+
bytesRemaining = -1;
132+
133+
// chunk trail
134+
await baseReader.ReadLineAsync();
135+
}
136+
}
137+
83138
public override void Flush()
84139
{
85140
throw new NotSupportedException();
@@ -131,6 +186,42 @@ public override int Read(byte[] buffer, int offset, int count)
131186
return res;
132187
}
133188

189+
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
190+
{
191+
if (bytesRemaining == -1)
192+
{
193+
return 0;
194+
}
195+
196+
if (bytesRemaining == 0)
197+
{
198+
if (isChunked)
199+
{
200+
await getNextChunkAsync();
201+
}
202+
else
203+
{
204+
bytesRemaining = -1;
205+
}
206+
}
207+
208+
if (bytesRemaining == -1)
209+
{
210+
return 0;
211+
}
212+
213+
int toRead = (int)Math.Min(count, bytesRemaining);
214+
int res = await baseReader.ReadAsync(buffer, offset, toRead, cancellationToken);
215+
bytesRemaining -= res;
216+
217+
if (res == 0)
218+
{
219+
bytesRemaining = -1;
220+
}
221+
222+
return res;
223+
}
224+
134225
public async Task Finish()
135226
{
136227
if (bytesRemaining != -1)

0 commit comments

Comments
 (0)