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

Commit f7c2490

Browse files
committed
remove connection cache causing errors when reusing
1 parent 3ff60c1 commit f7c2490

9 files changed

+171
-405
lines changed

Tests/Titanium.Web.Proxy.UnitTests/ConnectionManagerTests.cs

Lines changed: 0 additions & 85 deletions
This file was deleted.

Tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
</Choose>
5252
<ItemGroup>
5353
<Compile Include="CertificateManagerTests.cs" />
54-
<Compile Include="ConnectionManagerTests.cs" />
5554
<Compile Include="Properties\AssemblyInfo.cs" />
5655
</ItemGroup>
5756
<ItemGroup>

Titanium.Web.Proxy/Http/HttpWebClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class HttpWebClient
1717
/// <summary>
1818
/// Connection to server
1919
/// </summary>
20-
internal CachedTcpConnection ServerConnection { get; set; }
20+
internal TcpConnection ServerConnection { get; set; }
2121

2222
public Request Request { get; set; }
2323
public Response Response { get; set; }
@@ -37,7 +37,7 @@ public bool IsHttps
3737
/// Set the tcp connection to server used by this webclient
3838
/// </summary>
3939
/// <param name="Connection"></param>
40-
internal void SetConnection(CachedTcpConnection Connection)
40+
internal void SetConnection(TcpConnection Connection)
4141
{
4242
Connection.LastAccess = DateTime.Now;
4343
ServerConnection = Connection;

Titanium.Web.Proxy/Network/CachedTcpConnection.cs renamed to Titanium.Web.Proxy/Network/TcpConnection.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network
88
/// <summary>
99
/// An object that holds TcpConnection to a particular server & port
1010
/// </summary>
11-
public class CachedTcpConnection
11+
public class TcpConnection: IDisposable
1212
{
1313
internal string HostName { get; set; }
1414
internal int port { get; set; }
@@ -37,9 +37,15 @@ public class CachedTcpConnection
3737
/// </summary>
3838
internal DateTime LastAccess { get; set; }
3939

40-
internal CachedTcpConnection()
40+
internal TcpConnection()
4141
{
4242
LastAccess = DateTime.Now;
4343
}
44+
45+
public void Dispose()
46+
{
47+
Stream.Dispose();
48+
TcpClient.Client.Dispose();
49+
}
4450
}
4551
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Net.Sockets;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.IO;
8+
using System.Net.Security;
9+
using Titanium.Web.Proxy.Helpers;
10+
using System.Threading;
11+
using Titanium.Web.Proxy.Extensions;
12+
using Titanium.Web.Proxy.Models;
13+
using System.Security.Authentication;
14+
15+
namespace Titanium.Web.Proxy.Network
16+
{
17+
/// <summary>
18+
/// A class that manages Tcp Connection to server used by this proxy server
19+
/// </summary>
20+
internal class TcpConnectionFactory
21+
{
22+
/// <summary>
23+
/// Get a TcpConnection to the specified host, port optionally HTTPS and a particular HTTP version
24+
/// </summary>
25+
/// <param name="hostname"></param>
26+
/// <param name="port"></param>
27+
/// <param name="isHttps"></param>
28+
/// <param name="version"></param>
29+
/// <returns></returns>
30+
internal async Task<TcpConnection> GetClient(string hostname, int port, bool isHttps, Version version,
31+
ExternalProxy upStreamHttpProxy, ExternalProxy upStreamHttpsProxy, int bufferSize, SslProtocols supportedSslProtocols,
32+
int connectionTimeOutSeconds,
33+
RemoteCertificateValidationCallback remoteCertificateValidationCallBack,
34+
LocalCertificateSelectionCallback localCertificateSelectionCallback)
35+
{
36+
//not in cache so create and return
37+
return await CreateClient(hostname, port, isHttps, version, connectionTimeOutSeconds, upStreamHttpProxy, upStreamHttpsProxy, bufferSize, supportedSslProtocols,
38+
remoteCertificateValidationCallBack, localCertificateSelectionCallback);
39+
40+
}
41+
42+
43+
/// <summary>
44+
/// Create connection to a particular host/port optionally with SSL and a particular HTTP version
45+
/// </summary>
46+
/// <param name="hostname"></param>
47+
/// <param name="port"></param>
48+
/// <param name="isHttps"></param>
49+
/// <param name="version"></param>
50+
/// <returns></returns>
51+
private async Task<TcpConnection> CreateClient(string hostname, int port, bool isHttps, Version version, int connectionTimeOutSeconds,
52+
ExternalProxy upStreamHttpProxy, ExternalProxy upStreamHttpsProxy, int bufferSize, SslProtocols supportedSslProtocols,
53+
RemoteCertificateValidationCallback remoteCertificateValidationCallBack, LocalCertificateSelectionCallback localCertificateSelectionCallback)
54+
{
55+
TcpClient client;
56+
Stream stream;
57+
58+
if (isHttps)
59+
{
60+
SslStream sslStream = null;
61+
62+
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections
63+
if (upStreamHttpsProxy != null)
64+
{
65+
client = new TcpClient(upStreamHttpsProxy.HostName, upStreamHttpsProxy.Port);
66+
stream = client.GetStream();
67+
68+
using (var writer = new StreamWriter(stream, Encoding.ASCII, bufferSize, true))
69+
{
70+
await writer.WriteLineAsync(string.Format("CONNECT {0}:{1} {2}", hostname, port, version));
71+
await writer.WriteLineAsync(string.Format("Host: {0}:{1}", hostname, port));
72+
await writer.WriteLineAsync("Connection: Keep-Alive");
73+
await writer.WriteLineAsync();
74+
await writer.FlushAsync();
75+
writer.Close();
76+
}
77+
78+
using (var reader = new CustomBinaryReader(stream))
79+
{
80+
var result = await reader.ReadLineAsync();
81+
82+
if (!result.ToLower().Contains("200 connection established"))
83+
{
84+
throw new Exception("Upstream proxy failed to create a secure tunnel");
85+
}
86+
87+
await reader.ReadAllLinesAsync();
88+
}
89+
}
90+
else
91+
{
92+
client = new TcpClient(hostname, port);
93+
stream = client.GetStream();
94+
}
95+
96+
try
97+
{
98+
sslStream = new SslStream(stream, true, remoteCertificateValidationCallBack,
99+
localCertificateSelectionCallback);
100+
101+
await sslStream.AuthenticateAsClientAsync(hostname, null, supportedSslProtocols, false);
102+
103+
stream = sslStream;
104+
}
105+
catch
106+
{
107+
if (sslStream != null)
108+
{
109+
sslStream.Dispose();
110+
}
111+
112+
throw;
113+
}
114+
}
115+
else
116+
{
117+
if (upStreamHttpProxy != null)
118+
{
119+
client = new TcpClient(upStreamHttpProxy.HostName, upStreamHttpProxy.Port);
120+
stream = client.GetStream();
121+
}
122+
else
123+
{
124+
client = new TcpClient(hostname, port);
125+
stream = client.GetStream();
126+
}
127+
}
128+
129+
client.ReceiveTimeout = connectionTimeOutSeconds * 1000;
130+
client.SendTimeout = connectionTimeOutSeconds * 1000;
131+
132+
return new TcpConnection()
133+
{
134+
HostName = hostname,
135+
port = port,
136+
IsHttps = isHttps,
137+
TcpClient = client,
138+
StreamReader = new CustomBinaryReader(stream),
139+
Stream = stream,
140+
Version = version
141+
};
142+
}
143+
144+
145+
}
146+
}

0 commit comments

Comments
 (0)