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

Commit 48051d2

Browse files
committed
asyncify
add async for client/server ssl authentication
1 parent 90c53a5 commit 48051d2

File tree

4 files changed

+83
-34
lines changed

4 files changed

+83
-34
lines changed

Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs

+56-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.IO;
4+
using System.Net.Security;
5+
using System.Net.Sockets;
36
using System.Text;
7+
using Titanium.Web.Proxy.Network;
8+
using Titanium.Web.Proxy.Shared;
49

510
namespace Titanium.Web.Proxy.Helpers
611
{
@@ -9,13 +14,19 @@ namespace Titanium.Web.Proxy.Helpers
914
/// using the specified encoding
1015
/// as well as to read bytes as required
1116
/// </summary>
12-
public class CustomBinaryReader : BinaryReader
17+
public class CustomBinaryReader : IDisposable
1318
{
14-
internal CustomBinaryReader(Stream stream, Encoding encoding)
15-
: base(stream, encoding)
19+
private Stream stream;
20+
21+
22+
internal CustomBinaryReader(Stream stream)
1623
{
24+
this.stream = stream;
1725
}
1826

27+
28+
public Stream BaseStream => stream;
29+
1930
/// <summary>
2031
/// Read a line from the byte stream
2132
/// </summary>
@@ -27,9 +38,9 @@ internal string ReadLine()
2738
try
2839
{
2940
var lastChar = default(char);
30-
var buffer = new char[1];
41+
var buffer = new byte[1];
3142

32-
while (Read(buffer, 0, 1) > 0)
43+
while (this.stream.Read(buffer, 0, 1) > 0)
3344
{
3445
if (lastChar == '\r' && buffer[0] == '\n')
3546
{
@@ -39,8 +50,8 @@ internal string ReadLine()
3950
{
4051
return readBuffer.ToString();
4152
}
42-
readBuffer.Append(buffer);
43-
lastChar = buffer[0];
53+
readBuffer.Append((char)buffer[0]);
54+
lastChar = (char)buffer[0];
4455
}
4556

4657
return readBuffer.ToString();
@@ -65,5 +76,42 @@ internal List<string> ReadAllLines()
6576
}
6677
return requestLines;
6778
}
79+
80+
internal byte[] ReadBytes(long totalBytesToRead)
81+
{
82+
int bytesToRead = Constants.BUFFER_SIZE;
83+
84+
if (totalBytesToRead < Constants.BUFFER_SIZE)
85+
bytesToRead = (int)totalBytesToRead;
86+
87+
var buffer = new byte[Constants.BUFFER_SIZE];
88+
89+
var bytesRead = 0;
90+
var totalBytesRead = 0;
91+
92+
using (var outStream = new MemoryStream())
93+
{
94+
while ((bytesRead += this.stream.Read(buffer, 0, bytesToRead)) > 0)
95+
{
96+
outStream.Write(buffer, 0, bytesRead);
97+
totalBytesRead += bytesRead;
98+
99+
if (totalBytesRead == totalBytesToRead)
100+
break;
101+
102+
bytesRead = 0;
103+
var remainingBytes = (totalBytesToRead - totalBytesRead);
104+
bytesToRead = remainingBytes > (long)Constants.BUFFER_SIZE ? Constants.BUFFER_SIZE : (int)remainingBytes;
105+
}
106+
107+
return outStream.ToArray();
108+
}
109+
110+
}
111+
112+
public void Dispose()
113+
{
114+
115+
}
68116
}
69117
}

Titanium.Web.Proxy/Network/TcpConnectionManager.cs

+12-12
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal class TcpConnectionManager
3939
{
4040
static List<TcpConnection> ConnectionCache = new List<TcpConnection>();
4141

42-
internal static TcpConnection GetClient(SessionEventArgs sessionArgs, string hostname, int port, bool isSecure, Version version)
42+
internal static async Task<TcpConnection> GetClient(SessionEventArgs sessionArgs, string hostname, int port, bool isSecure, Version version)
4343
{
4444
TcpConnection cached = null;
4545
while (true)
@@ -61,18 +61,18 @@ internal static TcpConnection GetClient(SessionEventArgs sessionArgs, string hos
6161
}
6262

6363
if (cached == null)
64-
cached = CreateClient(sessionArgs,hostname, port, isSecure, version);
64+
cached = await CreateClient(sessionArgs,hostname, port, isSecure, version);
6565

66-
if (ConnectionCache.Where(x => x.HostName == hostname && x.port == port &&
67-
x.IsSecure == isSecure && x.TcpClient.Connected && x.Version.Equals(version)).Count() < 2)
68-
{
69-
Task.Factory.StartNew(() => CreateClient(sessionArgs, hostname, port, isSecure, version));
70-
}
66+
//if (ConnectionCache.Where(x => x.HostName == hostname && x.port == port &&
67+
//x.IsSecure == isSecure && x.TcpClient.Connected && x.Version.Equals(version)).Count() < 2)
68+
//{
69+
// Task.Factory.StartNew(() => CreateClient(sessionArgs, hostname, port, isSecure, version));
70+
//}
7171

7272
return cached;
7373
}
7474

75-
private static TcpConnection CreateClient(SessionEventArgs sessionArgs, string hostname, int port, bool isSecure, Version version)
75+
private static async Task<TcpConnection> CreateClient(SessionEventArgs sessionArgs, string hostname, int port, bool isSecure, Version version)
7676
{
7777
TcpClient client;
7878
Stream stream;
@@ -86,15 +86,15 @@ private static TcpConnection CreateClient(SessionEventArgs sessionArgs, string h
8686
client = new TcpClient(ProxyServer.UpStreamHttpsProxy.HostName, ProxyServer.UpStreamHttpsProxy.Port);
8787
stream = (Stream)client.GetStream();
8888

89-
var writer = new StreamWriter(stream);
89+
var writer = new StreamWriter(stream,Encoding.ASCII, Constants.BUFFER_SIZE, true);
9090

9191
writer.WriteLine(string.Format("CONNECT {0}:{1} {2}", sessionArgs.WebSession.Request.RequestUri.Host, sessionArgs.WebSession.Request.RequestUri.Port, sessionArgs.WebSession.Request.HttpVersion));
9292
writer.WriteLine(string.Format("Host: {0}:{1}", sessionArgs.WebSession.Request.RequestUri.Host, sessionArgs.WebSession.Request.RequestUri.Port));
9393
writer.WriteLine("Connection: Keep-Alive");
9494
writer.WriteLine();
9595
writer.Flush();
9696

97-
var reader = new CustomBinaryReader(stream, Encoding.ASCII);
97+
var reader = new CustomBinaryReader(stream);
9898
var result = reader.ReadLine();
9999

100100
if (!result.ToLower().Contains("200 connection established"))
@@ -112,7 +112,7 @@ private static TcpConnection CreateClient(SessionEventArgs sessionArgs, string h
112112
{
113113
sslStream = new CustomSslStream(stream, true, ProxyServer.ValidateServerCertificate);
114114
sslStream.Session = sessionArgs;
115-
sslStream.AuthenticateAsClient(hostname, null, Constants.SupportedProtocols, false);
115+
await sslStream.AuthenticateAsClientAsync(hostname, null, Constants.SupportedProtocols, false);
116116
stream = (Stream)sslStream;
117117
}
118118
catch
@@ -142,7 +142,7 @@ private static TcpConnection CreateClient(SessionEventArgs sessionArgs, string h
142142
port = port,
143143
IsSecure = isSecure,
144144
TcpClient = client,
145-
ServerStreamReader = new CustomBinaryReader(stream, Encoding.ASCII),
145+
ServerStreamReader = new CustomBinaryReader(stream),
146146
Stream = stream,
147147
Version = version
148148
};

Titanium.Web.Proxy/RequestHandler.cs

+14-13
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,17 @@
1616
using Titanium.Web.Proxy.Shared;
1717
using Titanium.Web.Proxy.Http;
1818
using Titanium.Web.Proxy.Extensions;
19+
using System.Threading.Tasks;
1920

2021
namespace Titanium.Web.Proxy
2122
{
2223
partial class ProxyServer
2324
{
2425
//This is called when client is aware of proxy
25-
private static void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient client)
26+
private static async void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient client)
2627
{
2728
Stream clientStream = client.GetStream();
28-
var clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
29+
var clientStreamReader = new CustomBinaryReader(clientStream);
2930
var clientStreamWriter = new StreamWriter(clientStream);
3031

3132
Uri httpRemoteUri;
@@ -75,10 +76,10 @@ private static void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient clien
7576
sslStream = new SslStream(clientStream, true);
7677

7778
//Successfully managed to authenticate the client using the fake certificate
78-
sslStream.AuthenticateAsServer(certificate, false,
79+
await sslStream.AuthenticateAsServerAsync(certificate, false,
7980
Constants.SupportedProtocols, false);
8081

81-
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
82+
clientStreamReader = new CustomBinaryReader(sslStream);
8283
clientStreamWriter = new StreamWriter(sslStream);
8384
//HTTPS server created - we can now decrypt the client's traffic
8485
clientStream = sslStream;
@@ -111,7 +112,7 @@ private static void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient clien
111112

112113
//Now create the request
113114

114-
HandleHttpSessionRequest(client, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
115+
await HandleHttpSessionRequest(client, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
115116
httpRemoteUri.Scheme == Uri.UriSchemeHttps ? true : false);
116117
}
117118
catch
@@ -122,7 +123,7 @@ private static void HandleClient(ExplicitProxyEndPoint endPoint, TcpClient clien
122123

123124
//This is called when requests are routed through router to this endpoint
124125
//For ssl requests
125-
private static void HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient)
126+
private static async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient)
126127
{
127128
Stream clientStream = tcpClient.GetStream();
128129
CustomBinaryReader clientStreamReader = null;
@@ -146,7 +147,7 @@ private static void HandleClient(TransparentProxyEndPoint endPoint, TcpClient tc
146147
sslStream.AuthenticateAsServer(certificate, false,
147148
SslProtocols.Tls, false);
148149

149-
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
150+
clientStreamReader = new CustomBinaryReader(sslStream);
150151
clientStreamWriter = new StreamWriter(sslStream);
151152
//HTTPS server created - we can now decrypt the client's traffic
152153

@@ -163,17 +164,17 @@ private static void HandleClient(TransparentProxyEndPoint endPoint, TcpClient tc
163164
}
164165
else
165166
{
166-
clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
167+
clientStreamReader = new CustomBinaryReader(clientStream);
167168
}
168169

169170
var httpCmd = clientStreamReader.ReadLine();
170171

171172
//Now create the request
172-
HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
173+
await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
173174
true);
174175
}
175176

176-
private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
177+
private static async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
177178
CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, bool IsHttps)
178179
{
179180
TcpConnection connection = null;
@@ -244,8 +245,8 @@ private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, S
244245

245246
//construct the web request that we are going to issue on behalf of the client.
246247
connection = connection == null ?
247-
TcpConnectionManager.GetClient(args, args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version)
248-
: lastRequestHostName != args.WebSession.Request.RequestUri.Host ? TcpConnectionManager.GetClient(args, args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version)
248+
await TcpConnectionManager.GetClient(args, args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version)
249+
: lastRequestHostName != args.WebSession.Request.RequestUri.Host ? await TcpConnectionManager.GetClient(args, args.WebSession.Request.RequestUri.Host, args.WebSession.Request.RequestUri.Port, args.IsHttps, version)
249250
: connection;
250251

251252
lastRequestHostName = args.WebSession.Request.RequestUri.Host;
@@ -288,7 +289,7 @@ private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, S
288289
if (args.WebSession.Request.RequestBodyRead)
289290
{
290291
args.WebSession.Request.ContentLength = args.WebSession.Request.RequestBody.Length;
291-
var newStream = args.WebSession.ProxyClient.ServerStreamReader.BaseStream;
292+
var newStream = args.WebSession.ProxyClient.Stream;
292293
newStream.Write(args.WebSession.Request.RequestBody, 0, args.WebSession.Request.RequestBody.Length);
293294
}
294295
else

Titanium.Web.Proxy/ResponseHandler.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public static void HandleHttpSessionResponse(SessionEventArgs args)
2323
try
2424
{
2525
if (!args.WebSession.Response.ResponseBodyRead)
26-
args.WebSession.Response.ResponseStream = args.WebSession.ProxyClient.ServerStreamReader.BaseStream;
26+
args.WebSession.Response.ResponseStream = args.WebSession.ProxyClient.Stream;
2727

2828

2929
if (BeforeResponse != null && !args.WebSession.Response.ResponseLocked)

0 commit comments

Comments
 (0)