Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
a954c575
Commit
a954c575
authored
Jun 17, 2016
by
Jehonathan
Committed by
GitHub
Jun 17, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #83 from justcoding121/cleanup
Make proxy non-static object
parents
82326b01
36a721b4
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
324 additions
and
262 deletions
+324
-262
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+22
-15
README.md
README.md
+2
-0
CertificateHandler.cs
Titanium.Web.Proxy/CertificateHandler.cs
+2
-2
DefaultDecompression.cs
Titanium.Web.Proxy/Decompression/DefaultDecompression.cs
+1
-1
DeflateDecompression.cs
Titanium.Web.Proxy/Decompression/DeflateDecompression.cs
+2
-2
GZipDecompression.cs
Titanium.Web.Proxy/Decompression/GZipDecompression.cs
+2
-2
IDecompression.cs
Titanium.Web.Proxy/Decompression/IDecompression.cs
+1
-1
ZlibDecompression.cs
Titanium.Web.Proxy/Decompression/ZlibDecompression.cs
+2
-2
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+31
-17
StreamExtensions.cs
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
+14
-14
CustomBinaryReader.cs
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
+5
-5
Firefox.cs
Titanium.Web.Proxy/Helpers/Firefox.cs
+3
-3
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+14
-12
Tcp.cs
Titanium.Web.Proxy/Helpers/Tcp.cs
+5
-4
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+8
-4
CertificateManager.cs
Titanium.Web.Proxy/Network/CertificateManager.cs
+11
-4
TcpConnectionCache.cs
Titanium.Web.Proxy/Network/TcpConnectionCache.cs
+2
-2
TcpConnectionCacheManager.cs
Titanium.Web.Proxy/Network/TcpConnectionCacheManager.cs
+35
-27
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+106
-83
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+38
-45
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+15
-10
ProxyConstants.cs
Titanium.Web.Proxy/Shared/ProxyConstants.cs
+1
-5
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+2
-2
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
a954c575
using
System
;
using
System
;
using
System.Collections.Generic
;
using
System.Net
;
using
System.Net
;
using
System.Text.RegularExpressions
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
...
@@ -10,12 +8,19 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -10,12 +8,19 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
{
public
class
ProxyTestController
public
class
ProxyTestController
{
{
private
ProxyServer
proxyServer
;
public
ProxyTestController
()
{
proxyServer
=
new
ProxyServer
();
}
public
void
StartProxy
()
public
void
StartProxy
()
{
{
P
roxyServer
.
BeforeRequest
+=
OnRequest
;
p
roxyServer
.
BeforeRequest
+=
OnRequest
;
P
roxyServer
.
BeforeResponse
+=
OnResponse
;
p
roxyServer
.
BeforeResponse
+=
OnResponse
;
P
roxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
p
roxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
P
roxyServer
.
ClientCertificateSelectionCallback
+=
OnCertificateSelection
;
p
roxyServer
.
ClientCertificateSelectionCallback
+=
OnCertificateSelection
;
//Exclude Https addresses you don't want to proxy
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
//Usefull for clients that use certificate pinning
...
@@ -27,8 +32,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -27,8 +32,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
//An explicit endpoint is where the client knows about the existance of a proxy
//An explicit endpoint is where the client knows about the existance of a proxy
//So client sends request in a proxy friendly manner
//So client sends request in a proxy friendly manner
P
roxyServer
.
AddEndPoint
(
explicitEndPoint
);
p
roxyServer
.
AddEndPoint
(
explicitEndPoint
);
P
roxyServer
.
Start
();
p
roxyServer
.
Start
();
//Transparent endpoint is usefull for reverse proxying (client is not aware of the existance of proxy)
//Transparent endpoint is usefull for reverse proxying (client is not aware of the existance of proxy)
...
@@ -41,26 +46,28 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -41,26 +46,28 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
{
GenericCertificateName
=
"google.com"
GenericCertificateName
=
"google.com"
};
};
P
roxyServer
.
AddEndPoint
(
transparentEndPoint
);
p
roxyServer
.
AddEndPoint
(
transparentEndPoint
);
//ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
foreach
(
var
endPoint
in
P
roxyServer
.
ProxyEndPoints
)
foreach
(
var
endPoint
in
p
roxyServer
.
ProxyEndPoints
)
Console
.
WriteLine
(
"Listening on '{0}' endpoint at Ip {1} and port: {2} "
,
Console
.
WriteLine
(
"Listening on '{0}' endpoint at Ip {1} and port: {2} "
,
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
//Only explicit proxies can be set as system proxy!
//Only explicit proxies can be set as system proxy!
P
roxyServer
.
SetAsSystemHttpProxy
(
explicitEndPoint
);
p
roxyServer
.
SetAsSystemHttpProxy
(
explicitEndPoint
);
P
roxyServer
.
SetAsSystemHttpsProxy
(
explicitEndPoint
);
p
roxyServer
.
SetAsSystemHttpsProxy
(
explicitEndPoint
);
}
}
public
void
Stop
()
public
void
Stop
()
{
{
ProxyServer
.
BeforeRequest
-=
OnRequest
;
proxyServer
.
BeforeRequest
-=
OnRequest
;
ProxyServer
.
BeforeResponse
-=
OnResponse
;
proxyServer
.
BeforeResponse
-=
OnResponse
;
proxyServer
.
ServerCertificateValidationCallback
-=
OnCertificateValidation
;
proxyServer
.
ClientCertificateSelectionCallback
-=
OnCertificateSelection
;
P
roxyServer
.
Stop
();
p
roxyServer
.
Stop
();
}
}
//intecept & cancel, redirect or update requests
//intecept & cancel, redirect or update requests
...
...
README.md
View file @
a954c575
...
@@ -35,6 +35,8 @@ After installing nuget package mark following files to be copied to app director
...
@@ -35,6 +35,8 @@ After installing nuget package mark following files to be copied to app director
Setup HTTP proxy:
Setup HTTP proxy:
```
csharp
```
csharp
var
ProxyServer
=
new
ProxyServer
();
ProxyServer
.
BeforeRequest
+=
OnRequest
;
ProxyServer
.
BeforeRequest
+=
OnRequest
;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
ProxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
ProxyServer
.
ServerCertificateValidationCallback
+=
OnCertificateValidation
;
...
...
Titanium.Web.Proxy/CertificateHandler.cs
View file @
a954c575
...
@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy
...
@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy
/// <param name="chain"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
bool
ValidateServerCertificate
(
internal
bool
ValidateServerCertificate
(
object
sender
,
object
sender
,
X509Certificate
certificate
,
X509Certificate
certificate
,
X509Chain
chain
,
X509Chain
chain
,
...
@@ -62,7 +62,7 @@ namespace Titanium.Web.Proxy
...
@@ -62,7 +62,7 @@ namespace Titanium.Web.Proxy
/// <param name="chain"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
X509Certificate
SelectClientCertificate
(
internal
X509Certificate
SelectClientCertificate
(
object
sender
,
object
sender
,
string
targetHost
,
string
targetHost
,
X509CertificateCollection
localCertificates
,
X509CertificateCollection
localCertificates
,
...
...
Titanium.Web.Proxy/Decompression/DefaultDecompression.cs
View file @
a954c575
...
@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Decompression
...
@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Decompression
/// </summary>
/// </summary>
internal
class
DefaultDecompression
:
IDecompression
internal
class
DefaultDecompression
:
IDecompression
{
{
public
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
public
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
,
int
bufferSize
)
{
{
return
Task
.
FromResult
(
compressedArray
);
return
Task
.
FromResult
(
compressedArray
);
}
}
...
...
Titanium.Web.Proxy/Decompression/DeflateDecompression.cs
View file @
a954c575
...
@@ -10,13 +10,13 @@ namespace Titanium.Web.Proxy.Decompression
...
@@ -10,13 +10,13 @@ namespace Titanium.Web.Proxy.Decompression
/// </summary>
/// </summary>
internal
class
DeflateDecompression
:
IDecompression
internal
class
DeflateDecompression
:
IDecompression
{
{
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
,
int
bufferSize
)
{
{
var
stream
=
new
MemoryStream
(
compressedArray
);
var
stream
=
new
MemoryStream
(
compressedArray
);
using
(
var
decompressor
=
new
DeflateStream
(
stream
,
CompressionMode
.
Decompress
))
using
(
var
decompressor
=
new
DeflateStream
(
stream
,
CompressionMode
.
Decompress
))
{
{
var
buffer
=
new
byte
[
ProxyConstants
.
BUFFER_SIZE
];
var
buffer
=
new
byte
[
bufferSize
];
using
(
var
output
=
new
MemoryStream
())
using
(
var
output
=
new
MemoryStream
())
{
{
...
...
Titanium.Web.Proxy/Decompression/GZipDecompression.cs
View file @
a954c575
...
@@ -10,11 +10,11 @@ namespace Titanium.Web.Proxy.Decompression
...
@@ -10,11 +10,11 @@ namespace Titanium.Web.Proxy.Decompression
/// </summary>
/// </summary>
internal
class
GZipDecompression
:
IDecompression
internal
class
GZipDecompression
:
IDecompression
{
{
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
,
int
bufferSize
)
{
{
using
(
var
decompressor
=
new
GZipStream
(
new
MemoryStream
(
compressedArray
),
CompressionMode
.
Decompress
))
using
(
var
decompressor
=
new
GZipStream
(
new
MemoryStream
(
compressedArray
),
CompressionMode
.
Decompress
))
{
{
var
buffer
=
new
byte
[
ProxyConstants
.
BUFFER_SIZE
];
var
buffer
=
new
byte
[
bufferSize
];
using
(
var
output
=
new
MemoryStream
())
using
(
var
output
=
new
MemoryStream
())
{
{
int
read
;
int
read
;
...
...
Titanium.Web.Proxy/Decompression/IDecompression.cs
View file @
a954c575
...
@@ -7,6 +7,6 @@ namespace Titanium.Web.Proxy.Decompression
...
@@ -7,6 +7,6 @@ namespace Titanium.Web.Proxy.Decompression
/// </summary>
/// </summary>
internal
interface
IDecompression
internal
interface
IDecompression
{
{
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
);
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
,
int
bufferSize
);
}
}
}
}
Titanium.Web.Proxy/Decompression/ZlibDecompression.cs
View file @
a954c575
...
@@ -10,12 +10,12 @@ namespace Titanium.Web.Proxy.Decompression
...
@@ -10,12 +10,12 @@ namespace Titanium.Web.Proxy.Decompression
/// </summary>
/// </summary>
internal
class
ZlibDecompression
:
IDecompression
internal
class
ZlibDecompression
:
IDecompression
{
{
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
,
int
bufferSize
)
{
{
var
memoryStream
=
new
MemoryStream
(
compressedArray
);
var
memoryStream
=
new
MemoryStream
(
compressedArray
);
using
(
var
decompressor
=
new
ZlibStream
(
memoryStream
,
CompressionMode
.
Decompress
))
using
(
var
decompressor
=
new
ZlibStream
(
memoryStream
,
CompressionMode
.
Decompress
))
{
{
var
buffer
=
new
byte
[
ProxyConstants
.
BUFFER_SIZE
];
var
buffer
=
new
byte
[
bufferSize
];
using
(
var
output
=
new
MemoryStream
())
using
(
var
output
=
new
MemoryStream
())
{
{
...
...
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
a954c575
...
@@ -20,14 +20,16 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -20,14 +20,16 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
/// </summary>
public
class
SessionEventArgs
:
EventArgs
,
IDisposable
public
class
SessionEventArgs
:
EventArgs
,
IDisposable
{
{
/// <summary>
/// <summary>
///
Constructor to initialize the proxy
///
Size of Buffers used by this object
/// </summary>
/// </summary>
internal
SessionEventArgs
()
private
readonly
int
bufferSize
;
{
ProxyClient
=
new
ProxyClient
();
/// <summary>
WebSession
=
new
HttpWebClient
();
/// Holds a reference to proxy response handler method
}
/// </summary>
private
readonly
Func
<
SessionEventArgs
,
Task
>
httpResponseHandler
;
/// <summary>
/// <summary>
/// Holds a reference to client
/// Holds a reference to client
...
@@ -50,13 +52,18 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -50,13 +52,18 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// <summary>
///
implement any cleanup here
///
Constructor to initialize the proxy
/// </summary>
/// </summary>
public
void
Dispose
(
)
internal
SessionEventArgs
(
int
bufferSize
,
Func
<
SessionEventArgs
,
Task
>
httpResponseHandler
)
{
{
this
.
bufferSize
=
bufferSize
;
this
.
httpResponseHandler
=
httpResponseHandler
;
ProxyClient
=
new
ProxyClient
();
WebSession
=
new
HttpWebClient
();
}
}
/// <summary>
/// <summary>
/// Read request body content as bytes[] for current session
/// Read request body content as bytes[] for current session
/// </summary>
/// </summary>
...
@@ -80,7 +87,7 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -80,7 +87,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
(
requestBodyStream
);
await
this
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStreamChunked
(
bufferSize
,
requestBodyStream
);
}
}
else
else
{
{
...
@@ -88,11 +95,11 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -88,11 +95,11 @@ 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
(
requestBodyStream
,
WebSession
.
Request
.
ContentLength
);
await
this
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
bufferSize
,
requestBodyStream
,
WebSession
.
Request
.
ContentLength
);
}
}
else
if
(
WebSession
.
Request
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Request
.
HttpVersion
.
Minor
==
0
)
else
if
(
WebSession
.
Request
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Request
.
HttpVersion
.
Minor
==
0
)
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
requestBodyStream
,
long
.
MaxValue
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
requestBodyStream
,
long
.
MaxValue
);
}
}
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
());
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
());
}
}
...
@@ -117,18 +124,18 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -117,18 +124,18 @@ namespace Titanium.Web.Proxy.EventArguments
//If chuncked the read chunk by chunk until we hit chunk end symbol
//If chuncked the read chunk by chunk until we hit chunk end symbol
if
(
WebSession
.
Response
.
IsChunked
)
if
(
WebSession
.
Response
.
IsChunked
)
{
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
responseBodyStream
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStreamChunked
(
bufferSize
,
responseBodyStream
);
}
}
else
else
{
{
if
(
WebSession
.
Response
.
ContentLength
>
0
)
if
(
WebSession
.
Response
.
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
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
}
}
else
if
(
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
else
if
(
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
long
.
MaxValue
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
long
.
MaxValue
);
}
}
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
...
@@ -285,7 +292,7 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -285,7 +292,7 @@ namespace Titanium.Web.Proxy.EventArguments
var
decompressionFactory
=
new
DecompressionFactory
();
var
decompressionFactory
=
new
DecompressionFactory
();
var
decompressor
=
decompressionFactory
.
Create
(
encodingType
);
var
decompressor
=
decompressionFactory
.
Create
(
encodingType
);
return
await
decompressor
.
Decompress
(
responseBodyStream
);
return
await
decompressor
.
Decompress
(
responseBodyStream
,
bufferSize
);
}
}
...
@@ -338,7 +345,7 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -338,7 +345,7 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession
.
Request
.
CancelRequest
=
true
;
WebSession
.
Request
.
CancelRequest
=
true
;
}
}
/// a generic responder method
/// a generic responder method
public
async
Task
Respond
(
Response
response
)
public
async
Task
Respond
(
Response
response
)
{
{
...
@@ -349,8 +356,15 @@ namespace Titanium.Web.Proxy.EventArguments
...
@@ -349,8 +356,15 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession
.
Response
=
response
;
WebSession
.
Response
=
response
;
await
ProxyServer
.
HandleHttpSessionResponse
(
this
);
await
httpResponseHandler
(
this
);
}
}
/// <summary>
/// implement any cleanup here
/// </summary>
public
void
Dispose
()
{
}
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
View file @
a954c575
...
@@ -35,22 +35,22 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -35,22 +35,22 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="stream"></param>
/// <param name="stream"></param>
/// <param name="totalBytesToRead"></param>
/// <param name="totalBytesToRead"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
CopyBytesToStream
(
this
CustomBinaryReader
streamReader
,
Stream
stream
,
long
totalBytesToRead
)
internal
static
async
Task
CopyBytesToStream
(
this
CustomBinaryReader
streamReader
,
int
bufferSize
,
Stream
stream
,
long
totalBytesToRead
)
{
{
var
totalbytesRead
=
0
;
var
totalbytesRead
=
0
;
long
bytesToRead
;
long
bytesToRead
;
if
(
totalBytesToRead
<
ProxyConstants
.
BUFFER_SIZE
)
if
(
totalBytesToRead
<
bufferSize
)
{
{
bytesToRead
=
totalBytesToRead
;
bytesToRead
=
totalBytesToRead
;
}
}
else
else
bytesToRead
=
ProxyConstants
.
BUFFER_SIZE
;
bytesToRead
=
bufferSize
;
while
(
totalbytesRead
<
totalBytesToRead
)
while
(
totalbytesRead
<
totalBytesToRead
)
{
{
var
buffer
=
await
streamReader
.
ReadBytesAsync
(
bytesToRead
);
var
buffer
=
await
streamReader
.
ReadBytesAsync
(
b
ufferSize
,
b
ytesToRead
);
if
(
buffer
.
Length
==
0
)
if
(
buffer
.
Length
==
0
)
break
;
break
;
...
@@ -72,7 +72,7 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -72,7 +72,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamReader"></param>
/// <param name="stream"></param>
/// <param name="stream"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
CopyBytesToStreamChunked
(
this
CustomBinaryReader
clientStreamReader
,
Stream
stream
)
internal
static
async
Task
CopyBytesToStreamChunked
(
this
CustomBinaryReader
clientStreamReader
,
int
bufferSize
,
Stream
stream
)
{
{
while
(
true
)
while
(
true
)
{
{
...
@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Extensions
if
(
chunkSize
!=
0
)
if
(
chunkSize
!=
0
)
{
{
var
buffer
=
await
clientStreamReader
.
ReadBytesAsync
(
chunkSize
);
var
buffer
=
await
clientStreamReader
.
ReadBytesAsync
(
bufferSize
,
chunkSize
);
await
stream
.
WriteAsync
(
buffer
,
0
,
buffer
.
Length
);
await
stream
.
WriteAsync
(
buffer
,
0
,
buffer
.
Length
);
//chunk trail
//chunk trail
await
clientStreamReader
.
ReadLineAsync
();
await
clientStreamReader
.
ReadLineAsync
();
...
@@ -118,7 +118,7 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -118,7 +118,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="isChunked"></param>
/// <param name="isChunked"></param>
/// <param name="ContentLength"></param>
/// <param name="ContentLength"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
WriteResponseBody
(
this
CustomBinaryReader
inStreamReader
,
Stream
outStream
,
bool
isChunked
,
long
ContentLength
)
internal
static
async
Task
WriteResponseBody
(
this
CustomBinaryReader
inStreamReader
,
int
bufferSize
,
Stream
outStream
,
bool
isChunked
,
long
ContentLength
)
{
{
if
(!
isChunked
)
if
(!
isChunked
)
{
{
...
@@ -126,12 +126,12 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -126,12 +126,12 @@ namespace Titanium.Web.Proxy.Extensions
if
(
ContentLength
==
-
1
)
if
(
ContentLength
==
-
1
)
ContentLength
=
long
.
MaxValue
;
ContentLength
=
long
.
MaxValue
;
int
bytesToRead
=
ProxyConstants
.
BUFFER_SIZE
;
int
bytesToRead
=
bufferSize
;
if
(
ContentLength
<
ProxyConstants
.
BUFFER_SIZE
)
if
(
ContentLength
<
bufferSize
)
bytesToRead
=
(
int
)
ContentLength
;
bytesToRead
=
(
int
)
ContentLength
;
var
buffer
=
new
byte
[
ProxyConstants
.
BUFFER_SIZE
];
var
buffer
=
new
byte
[
bufferSize
];
var
bytesRead
=
0
;
var
bytesRead
=
0
;
var
totalBytesRead
=
0
;
var
totalBytesRead
=
0
;
...
@@ -146,11 +146,11 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -146,11 +146,11 @@ namespace Titanium.Web.Proxy.Extensions
bytesRead
=
0
;
bytesRead
=
0
;
var
remainingBytes
=
(
ContentLength
-
totalBytesRead
);
var
remainingBytes
=
(
ContentLength
-
totalBytesRead
);
bytesToRead
=
remainingBytes
>
(
long
)
ProxyConstants
.
BUFFER_SIZE
?
ProxyConstants
.
BUFFER_SIZE
:
(
int
)
remainingBytes
;
bytesToRead
=
remainingBytes
>
(
long
)
bufferSize
?
bufferSize
:
(
int
)
remainingBytes
;
}
}
}
}
else
else
await
WriteResponseBodyChunked
(
inStreamReader
,
outStream
);
await
WriteResponseBodyChunked
(
inStreamReader
,
bufferSize
,
outStream
);
}
}
/// <summary>
/// <summary>
...
@@ -159,7 +159,7 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -159,7 +159,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="inStreamReader"></param>
/// <param name="inStreamReader"></param>
/// <param name="outStream"></param>
/// <param name="outStream"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
WriteResponseBodyChunked
(
this
CustomBinaryReader
inStreamReader
,
Stream
outStream
)
internal
static
async
Task
WriteResponseBodyChunked
(
this
CustomBinaryReader
inStreamReader
,
int
bufferSize
,
Stream
outStream
)
{
{
while
(
true
)
while
(
true
)
{
{
...
@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.Extensions
...
@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.Extensions
if
(
chunkSize
!=
0
)
if
(
chunkSize
!=
0
)
{
{
var
buffer
=
await
inStreamReader
.
ReadBytesAsync
(
chunkSize
);
var
buffer
=
await
inStreamReader
.
ReadBytesAsync
(
bufferSize
,
chunkSize
);
var
chunkHeadBytes
=
Encoding
.
ASCII
.
GetBytes
(
chunkSize
.
ToString
(
"x2"
));
var
chunkHeadBytes
=
Encoding
.
ASCII
.
GetBytes
(
chunkSize
.
ToString
(
"x2"
));
...
...
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
View file @
a954c575
...
@@ -91,14 +91,14 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -91,14 +91,14 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// </summary>
/// <param name="totalBytesToRead"></param>
/// <param name="totalBytesToRead"></param>
/// <returns></returns>
/// <returns></returns>
internal
async
Task
<
byte
[
]>
ReadBytesAsync
(
long
totalBytesToRead
)
internal
async
Task
<
byte
[
]>
ReadBytesAsync
(
int
bufferSize
,
long
totalBytesToRead
)
{
{
int
bytesToRead
=
ProxyConstants
.
BUFFER_SIZE
;
int
bytesToRead
=
bufferSize
;
if
(
totalBytesToRead
<
ProxyConstants
.
BUFFER_SIZE
)
if
(
totalBytesToRead
<
bufferSize
)
bytesToRead
=
(
int
)
totalBytesToRead
;
bytesToRead
=
(
int
)
totalBytesToRead
;
var
buffer
=
new
byte
[
ProxyConstants
.
BUFFER_SIZE
];
var
buffer
=
new
byte
[
bufferSize
];
var
bytesRead
=
0
;
var
bytesRead
=
0
;
var
totalBytesRead
=
0
;
var
totalBytesRead
=
0
;
...
@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers
bytesRead
=
0
;
bytesRead
=
0
;
var
remainingBytes
=
(
totalBytesToRead
-
totalBytesRead
);
var
remainingBytes
=
(
totalBytesToRead
-
totalBytesRead
);
bytesToRead
=
remainingBytes
>
(
long
)
ProxyConstants
.
BUFFER_SIZE
?
ProxyConstants
.
BUFFER_SIZE
:
(
int
)
remainingBytes
;
bytesToRead
=
remainingBytes
>
(
long
)
bufferSize
?
bufferSize
:
(
int
)
remainingBytes
;
}
}
return
outStream
.
ToArray
();
return
outStream
.
ToArray
();
...
...
Titanium.Web.Proxy/Helpers/Firefox.cs
View file @
a954c575
...
@@ -6,9 +6,9 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -6,9 +6,9 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// <summary>
/// A helper class to set proxy settings for firefox
/// A helper class to set proxy settings for firefox
/// </summary>
/// </summary>
public
class
FireFox
Help
er
public
class
FireFox
ProxySettingsManag
er
{
{
public
static
void
AddFirefox
()
public
void
AddFirefox
()
{
{
try
try
{
{
...
@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -38,7 +38,7 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
}
public
static
void
RemoveFirefox
()
public
void
RemoveFirefox
()
{
{
try
try
{
{
...
...
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
a954c575
...
@@ -11,7 +11,7 @@ using System.Linq;
...
@@ -11,7 +11,7 @@ using System.Linq;
namespace
Titanium.Web.Proxy.Helpers
namespace
Titanium.Web.Proxy.Helpers
{
{
internal
static
class
NativeMethods
internal
class
NativeMethods
{
{
[
DllImport
(
"wininet.dll"
)]
[
DllImport
(
"wininet.dll"
)]
internal
static
extern
bool
InternetSetOption
(
IntPtr
hInternet
,
int
dwOption
,
IntPtr
lpBuffer
,
internal
static
extern
bool
InternetSetOption
(
IntPtr
hInternet
,
int
dwOption
,
IntPtr
lpBuffer
,
...
@@ -32,13 +32,15 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -32,13 +32,15 @@ namespace Titanium.Web.Proxy.Helpers
return
"https="
+
HostName
+
":"
+
Port
;
return
"https="
+
HostName
+
":"
+
Port
;
}
}
}
}
/// <summary>
internal
static
class
SystemProxyHelper
/// Manage system proxy settings
/// </summary>
internal
class
SystemProxyManager
{
{
internal
const
int
InternetOptionSettingsChanged
=
39
;
internal
const
int
InternetOptionSettingsChanged
=
39
;
internal
const
int
InternetOptionRefresh
=
37
;
internal
const
int
InternetOptionRefresh
=
37
;
internal
static
void
SetHttpProxy
(
string
hostname
,
int
port
)
internal
void
SetHttpProxy
(
string
hostname
,
int
port
)
{
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
...
@@ -66,7 +68,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -66,7 +68,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// <summary>
/// Remove the http proxy setting from current machine
/// Remove the http proxy setting from current machine
/// </summary>
/// </summary>
internal
static
void
RemoveHttpProxy
()
internal
void
RemoveHttpProxy
()
{
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
...
@@ -100,7 +102,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -100,7 +102,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// </summary>
/// <param name="hostname"></param>
/// <param name="hostname"></param>
/// <param name="port"></param>
/// <param name="port"></param>
internal
static
void
SetHttpsProxy
(
string
hostname
,
int
port
)
internal
void
SetHttpsProxy
(
string
hostname
,
int
port
)
{
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
...
@@ -130,7 +132,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -130,7 +132,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// <summary>
/// Removes the https proxy setting to nothing
/// Removes the https proxy setting to nothing
/// </summary>
/// </summary>
internal
static
void
RemoveHttpsProxy
()
internal
void
RemoveHttpsProxy
()
{
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
...
@@ -163,7 +165,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -163,7 +165,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// <summary>
/// Removes all types of proxy settings (both http & https)
/// Removes all types of proxy settings (both http & https)
/// </summary>
/// </summary>
internal
static
void
DisableAllProxy
()
internal
void
DisableAllProxy
()
{
{
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
var
reg
=
Registry
.
CurrentUser
.
OpenSubKey
(
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
,
true
);
...
@@ -182,7 +184,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -182,7 +184,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// </summary>
/// <param name="prevServerValue"></param>
/// <param name="prevServerValue"></param>
/// <returns></returns>
/// <returns></returns>
private
static
List
<
HttpSystemProxyValue
>
GetSystemProxyValues
(
string
prevServerValue
)
private
List
<
HttpSystemProxyValue
>
GetSystemProxyValues
(
string
prevServerValue
)
{
{
var
result
=
new
List
<
HttpSystemProxyValue
>();
var
result
=
new
List
<
HttpSystemProxyValue
>();
...
@@ -215,7 +217,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -215,7 +217,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// </summary>
/// <param name="value"></param>
/// <param name="value"></param>
/// <returns></returns>
/// <returns></returns>
private
static
HttpSystemProxyValue
parseProxyValue
(
string
value
)
private
HttpSystemProxyValue
parseProxyValue
(
string
value
)
{
{
var
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
().
ToLower
();
var
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
().
ToLower
();
if
(
tmp
.
StartsWith
(
"http="
))
if
(
tmp
.
StartsWith
(
"http="
))
...
@@ -245,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -245,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers
/// Prepares the proxy server registry (create empty values if they don't exist)
/// Prepares the proxy server registry (create empty values if they don't exist)
/// </summary>
/// </summary>
/// <param name="reg"></param>
/// <param name="reg"></param>
private
static
void
prepareRegistry
(
RegistryKey
reg
)
private
void
prepareRegistry
(
RegistryKey
reg
)
{
{
if
(
reg
.
GetValue
(
"ProxyEnable"
)
==
null
)
if
(
reg
.
GetValue
(
"ProxyEnable"
)
==
null
)
{
{
...
@@ -262,7 +264,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -262,7 +264,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// <summary>
/// Refresh the settings so that the system know about a change in proxy setting
/// Refresh the settings so that the system know about a change in proxy setting
/// </summary>
/// </summary>
private
static
void
Refresh
()
private
void
Refresh
()
{
{
NativeMethods
.
InternetSetOption
(
IntPtr
.
Zero
,
InternetOptionSettingsChanged
,
IntPtr
.
Zero
,
0
);
NativeMethods
.
InternetSetOption
(
IntPtr
.
Zero
,
InternetOptionSettingsChanged
,
IntPtr
.
Zero
,
0
);
NativeMethods
.
InternetSetOption
(
IntPtr
.
Zero
,
InternetOptionRefresh
,
IntPtr
.
Zero
,
0
);
NativeMethods
.
InternetSetOption
(
IntPtr
.
Zero
,
InternetOptionRefresh
,
IntPtr
.
Zero
,
0
);
...
...
Titanium.Web.Proxy/Helpers/Tcp.cs
View file @
a954c575
...
@@ -4,6 +4,7 @@ using System.IO;
...
@@ -4,6 +4,7 @@ using System.IO;
using
System.Linq
;
using
System.Linq
;
using
System.Net.Security
;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Net.Sockets
;
using
System.Security.Authentication
;
using
System.Text
;
using
System.Text
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Extensions
;
...
@@ -12,7 +13,7 @@ using Titanium.Web.Proxy.Shared;
...
@@ -12,7 +13,7 @@ using Titanium.Web.Proxy.Shared;
namespace
Titanium.Web.Proxy.Helpers
namespace
Titanium.Web.Proxy.Helpers
{
{
internal
class
TcpHelper
internal
class
TcpHelper
{
{
/// <summary>
/// <summary>
...
@@ -26,8 +27,8 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -26,8 +27,8 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="tunnelPort"></param>
/// <param name="tunnelPort"></param>
/// <param name="isHttps"></param>
/// <param name="isHttps"></param>
/// <returns></returns>
/// <returns></returns>
internal
async
stati
c
Task
SendRaw
(
Stream
clientStream
,
string
httpCmd
,
List
<
HttpHeader
>
requestHeaders
,
string
hostName
,
internal
static
asyn
c
Task
SendRaw
(
Stream
clientStream
,
string
httpCmd
,
List
<
HttpHeader
>
requestHeaders
,
string
hostName
,
int
tunnelPort
,
bool
isHttps
)
int
tunnelPort
,
bool
isHttps
,
SslProtocols
supportedProtocols
)
{
{
//prepare the prefix content
//prepare the prefix content
StringBuilder
sb
=
null
;
StringBuilder
sb
=
null
;
...
@@ -63,7 +64,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -63,7 +64,7 @@ namespace Titanium.Web.Proxy.Helpers
try
try
{
{
sslStream
=
new
SslStream
(
tunnelStream
);
sslStream
=
new
SslStream
(
tunnelStream
);
await
sslStream
.
AuthenticateAsClientAsync
(
hostName
,
null
,
ProxyConstants
.
SupportedSsl
Protocols
,
false
);
await
sslStream
.
AuthenticateAsClientAsync
(
hostName
,
null
,
supported
Protocols
,
false
);
tunnelStream
=
sslStream
;
tunnelStream
=
sslStream
;
}
}
catch
catch
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
a954c575
...
@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// <summary>
/// Connection to server
/// Connection to server
/// </summary>
/// </summary>
internal
TcpConnection
ServerConnection
{
get
;
set
;
}
internal
TcpConnection
Cache
ServerConnection
{
get
;
set
;
}
public
Request
Request
{
get
;
set
;
}
public
Request
Request
{
get
;
set
;
}
public
Response
Response
{
get
;
set
;
}
public
Response
Response
{
get
;
set
;
}
...
@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.Http
/// Set the tcp connection to server used by this webclient
/// Set the tcp connection to server used by this webclient
/// </summary>
/// </summary>
/// <param name="Connection"></param>
/// <param name="Connection"></param>
internal
void
SetConnection
(
TcpConnection
Connection
)
internal
void
SetConnection
(
TcpConnection
Cache
Connection
)
{
{
Connection
.
LastAccess
=
DateTime
.
Now
;
Connection
.
LastAccess
=
DateTime
.
Now
;
ServerConnection
=
Connection
;
ServerConnection
=
Connection
;
...
@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy.Http
/// Prepare & send the http(s) request
/// Prepare & send the http(s) request
/// </summary>
/// </summary>
/// <returns></returns>
/// <returns></returns>
internal
async
Task
SendRequest
()
internal
async
Task
SendRequest
(
bool
enable100ContinueBehaviour
)
{
{
Stream
stream
=
ServerConnection
.
Stream
;
Stream
stream
=
ServerConnection
.
Stream
;
...
@@ -79,7 +79,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -79,7 +79,7 @@ namespace Titanium.Web.Proxy.Http
await
stream
.
WriteAsync
(
requestBytes
,
0
,
requestBytes
.
Length
);
await
stream
.
WriteAsync
(
requestBytes
,
0
,
requestBytes
.
Length
);
await
stream
.
FlushAsync
();
await
stream
.
FlushAsync
();
if
(
ProxyServer
.
E
nable100ContinueBehaviour
)
if
(
e
nable100ContinueBehaviour
)
if
(
this
.
Request
.
ExpectContinue
)
if
(
this
.
Request
.
ExpectContinue
)
{
{
var
httpResult
=
(
await
ServerConnection
.
StreamReader
.
ReadLineAsync
()).
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
var
httpResult
=
(
await
ServerConnection
.
StreamReader
.
ReadLineAsync
()).
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
...
@@ -133,18 +133,22 @@ namespace Titanium.Web.Proxy.Http
...
@@ -133,18 +133,22 @@ namespace Titanium.Web.Proxy.Http
if
(
this
.
Response
.
ResponseStatusCode
.
Equals
(
"100"
)
if
(
this
.
Response
.
ResponseStatusCode
.
Equals
(
"100"
)
&&
this
.
Response
.
ResponseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
&&
this
.
Response
.
ResponseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
{
{
//Read the next line after 100-continue
this
.
Response
.
Is100Continue
=
true
;
this
.
Response
.
Is100Continue
=
true
;
this
.
Response
.
ResponseStatusCode
=
null
;
this
.
Response
.
ResponseStatusCode
=
null
;
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
//now receive response
await
ReceiveResponse
();
await
ReceiveResponse
();
return
;
return
;
}
}
else
if
(
this
.
Response
.
ResponseStatusCode
.
Equals
(
"417"
)
else
if
(
this
.
Response
.
ResponseStatusCode
.
Equals
(
"417"
)
&&
this
.
Response
.
ResponseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
&&
this
.
Response
.
ResponseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
{
{
//read next line after expectation failed response
this
.
Response
.
ExpectationFailed
=
true
;
this
.
Response
.
ExpectationFailed
=
true
;
this
.
Response
.
ResponseStatusCode
=
null
;
this
.
Response
.
ResponseStatusCode
=
null
;
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
//now receive response
await
ReceiveResponse
();
await
ReceiveResponse
();
return
;
return
;
}
}
...
...
Titanium.Web.Proxy/Network/CertificateManager.cs
View file @
a954c575
...
@@ -18,8 +18,15 @@ namespace Titanium.Web.Proxy.Network
...
@@ -18,8 +18,15 @@ namespace Titanium.Web.Proxy.Network
private
const
string
CertCreateFormat
=
private
const
string
CertCreateFormat
=
"-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 {5}"
;
"-ss {0} -n \"CN={1}, O={2}\" -sky {3} -cy {4} -m 120 -a sha256 -eku 1.3.6.1.5.5.7.3.1 {5}"
;
/// <summary>
/// Cache dictionary
/// </summary>
private
readonly
IDictionary
<
string
,
CachedCertificate
>
certificateCache
;
private
readonly
IDictionary
<
string
,
CachedCertificate
>
certificateCache
;
private
static
SemaphoreSlim
semaphoreLock
=
new
SemaphoreSlim
(
1
);
/// <summary>
/// A lock to manage concurrency
/// </summary>
private
SemaphoreSlim
semaphoreLock
=
new
SemaphoreSlim
(
1
);
internal
string
Issuer
{
get
;
private
set
;
}
internal
string
Issuer
{
get
;
private
set
;
}
internal
string
RootCertificateName
{
get
;
private
set
;
}
internal
string
RootCertificateName
{
get
;
private
set
;
}
...
@@ -241,7 +248,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -241,7 +248,7 @@ namespace Titanium.Web.Proxy.Network
return
certCreatArgs
;
return
certCreatArgs
;
}
}
private
static
bool
clearCertificates
{
get
;
set
;
}
private
bool
clearCertificates
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Stops the certificate cache clear process
/// Stops the certificate cache clear process
...
@@ -254,7 +261,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -254,7 +261,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// <summary>
/// A method to clear outdated certificates
/// A method to clear outdated certificates
/// </summary>
/// </summary>
internal
async
void
ClearIdleCertificates
()
internal
async
void
ClearIdleCertificates
(
int
certificateCacheTimeOutMinutes
)
{
{
clearCertificates
=
true
;
clearCertificates
=
true
;
while
(
clearCertificates
)
while
(
clearCertificates
)
...
@@ -263,7 +270,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -263,7 +270,7 @@ namespace Titanium.Web.Proxy.Network
try
try
{
{
var
cutOff
=
DateTime
.
Now
.
AddMinutes
(-
1
*
ProxyServer
.
C
ertificateCacheTimeOutMinutes
);
var
cutOff
=
DateTime
.
Now
.
AddMinutes
(-
1
*
c
ertificateCacheTimeOutMinutes
);
var
outdated
=
certificateCache
var
outdated
=
certificateCache
.
Where
(
x
=>
x
.
Value
.
LastAccess
<
cutOff
)
.
Where
(
x
=>
x
.
Value
.
LastAccess
<
cutOff
)
...
...
Titanium.Web.Proxy/Network/TcpConnection.cs
→
Titanium.Web.Proxy/Network/TcpConnection
Cache
.cs
View file @
a954c575
...
@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// <summary>
/// An object that holds TcpConnection to a particular server & port
/// An object that holds TcpConnection to a particular server & port
/// </summary>
/// </summary>
public
class
TcpConnection
public
class
TcpConnection
Cache
{
{
internal
string
HostName
{
get
;
set
;
}
internal
string
HostName
{
get
;
set
;
}
internal
int
port
{
get
;
set
;
}
internal
int
port
{
get
;
set
;
}
...
@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.Network
/// </summary>
/// </summary>
internal
DateTime
LastAccess
{
get
;
set
;
}
internal
DateTime
LastAccess
{
get
;
set
;
}
internal
TcpConnection
()
internal
TcpConnection
Cache
()
{
{
LastAccess
=
DateTime
.
Now
;
LastAccess
=
DateTime
.
Now
;
}
}
...
...
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
→
Titanium.Web.Proxy/Network/TcpConnection
Cache
Manager.cs
View file @
a954c575
...
@@ -10,23 +10,25 @@ using Titanium.Web.Proxy.Helpers;
...
@@ -10,23 +10,25 @@ using Titanium.Web.Proxy.Helpers;
using
System.Threading
;
using
System.Threading
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Shared
;
using
Titanium.Web.Proxy.Shared
;
using
Titanium.Web.Proxy.Models
;
using
System.Security.Authentication
;
namespace
Titanium.Web.Proxy.Network
namespace
Titanium.Web.Proxy.Network
{
{
/// <summary>
/// <summary>
/// A class that manages Tcp Connection to server used by this proxy server
/// A class that manages Tcp Connection to server used by this proxy server
/// </summary>
/// </summary>
internal
class
TcpConnectionManager
internal
class
TcpConnection
Cache
Manager
{
{
/// <summary>
/// <summary>
/// Connection cache
/// Connection cache
/// </summary>
/// </summary>
static
Dictionary
<
string
,
List
<
TcpConnection
>>
connectionCache
=
new
Dictionary
<
string
,
List
<
TcpConnection
>>();
Dictionary
<
string
,
List
<
TcpConnectionCache
>>
connectionCache
=
new
Dictionary
<
string
,
List
<
TcpConnectionCache
>>();
/// <summary>
/// <summary>
/// A lock to manage concurrency
/// A lock to manage concurrency
/// </summary>
/// </summary>
static
SemaphoreSlim
connectionAccessLock
=
new
SemaphoreSlim
(
1
);
SemaphoreSlim
connectionAccessLock
=
new
SemaphoreSlim
(
1
);
/// <summary>
/// <summary>
/// Get a TcpConnection to the specified host, port optionally HTTPS and a particular HTTP version
/// Get a TcpConnection to the specified host, port optionally HTTPS and a particular HTTP version
...
@@ -36,10 +38,12 @@ namespace Titanium.Web.Proxy.Network
...
@@ -36,10 +38,12 @@ namespace Titanium.Web.Proxy.Network
/// <param name="isHttps"></param>
/// <param name="isHttps"></param>
/// <param name="version"></param>
/// <param name="version"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
<
TcpConnection
>
GetClient
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
internal
async
Task
<
TcpConnectionCache
>
GetClient
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
,
ExternalProxy
upStreamHttpProxy
,
ExternalProxy
upStreamHttpsProxy
,
int
bufferSize
,
SslProtocols
supportedSslProtocols
,
RemoteCertificateValidationCallback
remoteCertificateValidationCallBack
,
LocalCertificateSelectionCallback
localCertificateSelectionCallback
)
{
{
List
<
TcpConnection
>
cachedConnections
=
null
;
List
<
TcpConnection
Cache
>
cachedConnections
=
null
;
TcpConnection
cached
=
null
;
TcpConnection
Cache
cached
=
null
;
//Get a unique string to identify this connection
//Get a unique string to identify this connection
var
key
=
GetConnectionKey
(
hostname
,
port
,
isHttps
,
version
);
var
key
=
GetConnectionKey
(
hostname
,
port
,
isHttps
,
version
);
...
@@ -77,12 +81,14 @@ namespace Titanium.Web.Proxy.Network
...
@@ -77,12 +81,14 @@ namespace Titanium.Web.Proxy.Network
if
(
cached
==
null
)
if
(
cached
==
null
)
cached
=
await
CreateClient
(
hostname
,
port
,
isHttps
,
version
);
cached
=
await
CreateClient
(
hostname
,
port
,
isHttps
,
version
,
upStreamHttpProxy
,
upStreamHttpsProxy
,
bufferSize
,
supportedSslProtocols
,
remoteCertificateValidationCallBack
,
localCertificateSelectionCallback
);
if
(
cachedConnections
==
null
||
cachedConnections
.
Count
()
<=
2
)
if
(
cachedConnections
==
null
||
cachedConnections
.
Count
()
<=
2
)
{
{
var
task
=
CreateClient
(
hostname
,
port
,
isHttps
,
version
)
var
task
=
CreateClient
(
hostname
,
port
,
isHttps
,
version
,
upStreamHttpProxy
,
upStreamHttpsProxy
,
bufferSize
,
supportedSslProtocols
,
.
ContinueWith
(
async
(
x
)
=>
{
if
(
x
.
Status
==
TaskStatus
.
RanToCompletion
)
await
ReleaseClient
(
x
.
Result
);
});
remoteCertificateValidationCallBack
,
localCertificateSelectionCallback
)
.
ContinueWith
(
async
(
x
)
=>
{
if
(
x
.
Status
==
TaskStatus
.
RanToCompletion
)
await
ReleaseClient
(
x
.
Result
);
});
}
}
return
cached
;
return
cached
;
...
@@ -96,7 +102,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -96,7 +102,7 @@ namespace Titanium.Web.Proxy.Network
/// <param name="isHttps"></param>
/// <param name="isHttps"></param>
/// <param name="version"></param>
/// <param name="version"></param>
/// <returns></returns>
/// <returns></returns>
internal
st
atic
st
ring
GetConnectionKey
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
internal
string
GetConnectionKey
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
{
{
return
string
.
Format
(
"{0}:{1}:{2}:{3}:{4}"
,
hostname
.
ToLower
(),
port
,
isHttps
,
version
.
Major
,
version
.
Minor
);
return
string
.
Format
(
"{0}:{1}:{2}:{3}:{4}"
,
hostname
.
ToLower
(),
port
,
isHttps
,
version
.
Major
,
version
.
Minor
);
}
}
...
@@ -109,7 +115,9 @@ namespace Titanium.Web.Proxy.Network
...
@@ -109,7 +115,9 @@ namespace Titanium.Web.Proxy.Network
/// <param name="isHttps"></param>
/// <param name="isHttps"></param>
/// <param name="version"></param>
/// <param name="version"></param>
/// <returns></returns>
/// <returns></returns>
private
static
async
Task
<
TcpConnection
>
CreateClient
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
)
private
async
Task
<
TcpConnectionCache
>
CreateClient
(
string
hostname
,
int
port
,
bool
isHttps
,
Version
version
,
ExternalProxy
upStreamHttpProxy
,
ExternalProxy
upStreamHttpsProxy
,
int
bufferSize
,
SslProtocols
supportedSslProtocols
,
RemoteCertificateValidationCallback
remoteCertificateValidationCallBack
,
LocalCertificateSelectionCallback
localCertificateSelectionCallback
)
{
{
TcpClient
client
;
TcpClient
client
;
Stream
stream
;
Stream
stream
;
...
@@ -119,12 +127,12 @@ namespace Titanium.Web.Proxy.Network
...
@@ -119,12 +127,12 @@ namespace Titanium.Web.Proxy.Network
SslStream
sslStream
=
null
;
SslStream
sslStream
=
null
;
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections
if
(
ProxyServer
.
U
pStreamHttpsProxy
!=
null
)
if
(
u
pStreamHttpsProxy
!=
null
)
{
{
client
=
new
TcpClient
(
ProxyServer
.
UpStreamHttpsProxy
.
HostName
,
ProxyServer
.
U
pStreamHttpsProxy
.
Port
);
client
=
new
TcpClient
(
upStreamHttpsProxy
.
HostName
,
u
pStreamHttpsProxy
.
Port
);
stream
=
(
Stream
)
client
.
GetStream
();
stream
=
(
Stream
)
client
.
GetStream
();
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
ProxyConstants
.
BUFFER_SIZE
,
true
))
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
bufferSize
,
true
))
{
{
await
writer
.
WriteLineAsync
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
hostname
,
port
,
version
));
await
writer
.
WriteLineAsync
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
hostname
,
port
,
version
));
await
writer
.
WriteLineAsync
(
string
.
Format
(
"Host: {0}:{1}"
,
hostname
,
port
));
await
writer
.
WriteLineAsync
(
string
.
Format
(
"Host: {0}:{1}"
,
hostname
,
port
));
...
@@ -152,9 +160,9 @@ namespace Titanium.Web.Proxy.Network
...
@@ -152,9 +160,9 @@ namespace Titanium.Web.Proxy.Network
try
try
{
{
sslStream
=
new
SslStream
(
stream
,
true
,
new
RemoteCertificateValidationCallback
(
ProxyServer
.
ValidateServerCertificate
)
,
sslStream
=
new
SslStream
(
stream
,
true
,
remoteCertificateValidationCallBack
,
new
LocalCertificateSelectionCallback
(
ProxyServer
.
SelectClientCertificate
)
);
localCertificateSelectionCallback
);
await
sslStream
.
AuthenticateAsClientAsync
(
hostname
,
null
,
ProxyConstants
.
S
upportedSslProtocols
,
false
);
await
sslStream
.
AuthenticateAsClientAsync
(
hostname
,
null
,
s
upportedSslProtocols
,
false
);
stream
=
(
Stream
)
sslStream
;
stream
=
(
Stream
)
sslStream
;
}
}
catch
catch
...
@@ -166,9 +174,9 @@ namespace Titanium.Web.Proxy.Network
...
@@ -166,9 +174,9 @@ namespace Titanium.Web.Proxy.Network
}
}
else
else
{
{
if
(
ProxyServer
.
U
pStreamHttpProxy
!=
null
)
if
(
u
pStreamHttpProxy
!=
null
)
{
{
client
=
new
TcpClient
(
ProxyServer
.
UpStreamHttpProxy
.
HostName
,
ProxyServer
.
U
pStreamHttpProxy
.
Port
);
client
=
new
TcpClient
(
upStreamHttpProxy
.
HostName
,
u
pStreamHttpProxy
.
Port
);
stream
=
(
Stream
)
client
.
GetStream
();
stream
=
(
Stream
)
client
.
GetStream
();
}
}
else
else
...
@@ -178,7 +186,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -178,7 +186,7 @@ namespace Titanium.Web.Proxy.Network
}
}
}
}
return
new
TcpConnection
()
return
new
TcpConnection
Cache
()
{
{
HostName
=
hostname
,
HostName
=
hostname
,
port
=
port
,
port
=
port
,
...
@@ -195,7 +203,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -195,7 +203,7 @@ namespace Titanium.Web.Proxy.Network
/// </summary>
/// </summary>
/// <param name="connection"></param>
/// <param name="connection"></param>
/// <returns></returns>
/// <returns></returns>
internal
static
async
Task
ReleaseClient
(
TcpConnection
connection
)
internal
async
Task
ReleaseClient
(
TcpConnectionCache
connection
)
{
{
connection
.
LastAccess
=
DateTime
.
Now
;
connection
.
LastAccess
=
DateTime
.
Now
;
...
@@ -203,25 +211,25 @@ namespace Titanium.Web.Proxy.Network
...
@@ -203,25 +211,25 @@ namespace Titanium.Web.Proxy.Network
await
connectionAccessLock
.
WaitAsync
();
await
connectionAccessLock
.
WaitAsync
();
try
try
{
{
List
<
TcpConnection
>
cachedConnections
;
List
<
TcpConnection
Cache
>
cachedConnections
;
connectionCache
.
TryGetValue
(
key
,
out
cachedConnections
);
connectionCache
.
TryGetValue
(
key
,
out
cachedConnections
);
if
(
cachedConnections
!=
null
)
if
(
cachedConnections
!=
null
)
cachedConnections
.
Add
(
connection
);
cachedConnections
.
Add
(
connection
);
else
else
connectionCache
.
Add
(
key
,
new
List
<
TcpConnection
>()
{
connection
});
connectionCache
.
Add
(
key
,
new
List
<
TcpConnection
Cache
>()
{
connection
});
}
}
finally
{
connectionAccessLock
.
Release
();
}
finally
{
connectionAccessLock
.
Release
();
}
}
}
private
static
bool
clearConenctions
{
get
;
set
;
}
private
bool
clearConenctions
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Stop clearing idle connections
/// Stop clearing idle connections
/// </summary>
/// </summary>
internal
static
void
StopClearIdleConnections
()
internal
void
StopClearIdleConnections
()
{
{
clearConenctions
=
false
;
clearConenctions
=
false
;
}
}
...
@@ -229,7 +237,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -229,7 +237,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// <summary>
/// A method to clear idle connections
/// A method to clear idle connections
/// </summary>
/// </summary>
internal
async
static
void
ClearIdleConnections
(
)
internal
async
void
ClearIdleConnections
(
int
connectionCacheTimeOutMinutes
)
{
{
clearConenctions
=
true
;
clearConenctions
=
true
;
while
(
clearConenctions
)
while
(
clearConenctions
)
...
@@ -237,7 +245,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -237,7 +245,7 @@ namespace Titanium.Web.Proxy.Network
await
connectionAccessLock
.
WaitAsync
();
await
connectionAccessLock
.
WaitAsync
();
try
try
{
{
var
cutOff
=
DateTime
.
Now
.
AddMinutes
(-
1
*
ProxyServer
.
C
onnectionCacheTimeOutMinutes
);
var
cutOff
=
DateTime
.
Now
.
AddMinutes
(-
1
*
c
onnectionCacheTimeOutMinutes
);
connectionCache
connectionCache
.
SelectMany
(
x
=>
x
.
Value
)
.
SelectMany
(
x
=>
x
.
Value
)
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
a954c575
...
@@ -8,126 +8,144 @@ using Titanium.Web.Proxy.Helpers;
...
@@ -8,126 +8,144 @@ using Titanium.Web.Proxy.Helpers;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network
;
using
System.Linq
;
using
System.Linq
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Security.Authentication
;
using
System.Net.Security
;
namespace
Titanium.Web.Proxy
namespace
Titanium.Web.Proxy
{
{
/// <summary>
/// <summary>
/// Proxy Server Main class
/// Proxy Server Main class
/// </summary>
/// </summary>
public
partial
class
ProxyServer
public
partial
class
ProxyServer
:
IDisposable
{
{
/// <summary>
/// Manages certificates used by this proxy
/// </summary>
private
CertificateManager
certificateCacheManager
{
get
;
set
;
}
static
ProxyServer
()
/// <summary>
{
/// A object that manages tcp connection cache to server
ProxyEndPoints
=
new
List
<
ProxyEndPoint
>();
/// </summary>
private
TcpConnectionCacheManager
tcpConnectionCacheManager
{
get
;
set
;
}
//default values
ConnectionCacheTimeOutMinutes
=
3
;
CertificateCacheTimeOutMinutes
=
60
;
}
/// <summary>
/// <summary>
/// Manage
s certificates used by this proxy
/// Manage
system proxy settings
/// </summary>
/// </summary>
private
static
CertificateManager
CertManager
{
get
;
set
;
}
private
SystemProxyManager
systemProxySettingsManager
{
get
;
set
;
}
private
FireFoxProxySettingsManager
firefoxProxySettingsManager
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Does the root certificate used by this proxy is trusted by the machine?
/// Does the root certificate used by this proxy is trusted by the machine?
/// </summary>
/// </summary>
private
static
bool
certTrusted
{
get
;
set
;
}
private
bool
certTrusted
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Is the proxy currently running
/// Is the proxy currently running
/// </summary>
/// </summary>
private
static
bool
proxyRunning
{
get
;
set
;
}
private
bool
proxyRunning
{
get
;
set
;
}
/// <summary>
/// Buffer size used throughout this proxy
/// </summary>
public
int
BUFFER_SIZE
{
get
;
set
;
}
=
8192
;
/// <summary>
/// <summary>
/// Name of the root certificate issuer
/// Name of the root certificate issuer
/// </summary>
/// </summary>
public
st
atic
st
ring
RootCertificateIssuerName
{
get
;
set
;
}
public
string
RootCertificateIssuerName
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Name of the root certificate
/// Name of the root certificate
/// </summary>
/// </summary>
public
st
atic
st
ring
RootCertificateName
{
get
;
set
;
}
public
string
RootCertificateName
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Does this proxy uses the HTTP protocol 100 continue behaviour strictly?
/// Does this proxy uses the HTTP protocol 100 continue behaviour strictly?
/// Broken 100 contunue implementations on server/client may cause problems if enabled
/// Broken 100 contunue implementations on server/client may cause problems if enabled
/// </summary>
/// </summary>
public
static
bool
Enable100ContinueBehaviour
{
get
;
set
;
}
public
bool
Enable100ContinueBehaviour
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Minutes TCP connection cache to servers to be kept alive when in idle state
/// Minutes TCP connection cache to servers to be kept alive when in idle state
/// </summary>
/// </summary>
public
static
int
ConnectionCacheTimeOutMinutes
{
get
;
set
;
}
public
int
ConnectionCacheTimeOutMinutes
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Minutes certificates should be kept in cache when not used
/// Minutes certificates should be kept in cache when not used
/// </summary>
/// </summary>
public
static
int
CertificateCacheTimeOutMinutes
{
get
;
set
;
}
public
int
CertificateCacheTimeOutMinutes
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Intercept request to server
/// Intercept request to server
/// </summary>
/// </summary>
public
static
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeRequest
;
public
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeRequest
;
/// <summary>
/// <summary>
/// Intercept response from server
/// Intercept response from server
/// </summary>
/// </summary>
public
static
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeResponse
;
public
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeResponse
;
/// <summary>
/// <summary>
/// External proxy for Http
/// External proxy for Http
/// </summary>
/// </summary>
public
static
ExternalProxy
UpStreamHttpProxy
{
get
;
set
;
}
public
ExternalProxy
UpStreamHttpProxy
{
get
;
set
;
}
/// <summary>
/// <summary>
/// External proxy for Http
/// External proxy for Http
/// </summary>
/// </summary>
public
static
ExternalProxy
UpStreamHttpsProxy
{
get
;
set
;
}
public
ExternalProxy
UpStreamHttpsProxy
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary>
/// </summary>
public
static
event
Func
<
object
,
CertificateValidationEventArgs
,
Task
>
ServerCertificateValidationCallback
;
public
event
Func
<
object
,
CertificateValidationEventArgs
,
Task
>
ServerCertificateValidationCallback
;
/// <summary>
/// <summary>
/// Callback tooverride client certificate during SSL mutual authentication
/// Callback tooverride client certificate during SSL mutual authentication
/// </summary>
/// </summary>
public
static
event
Func
<
object
,
CertificateSelectionEventArgs
,
Task
>
ClientCertificateSelectionCallback
;
public
event
Func
<
object
,
CertificateSelectionEventArgs
,
Task
>
ClientCertificateSelectionCallback
;
/// <summary>
/// <summary>
/// A list of IpAddress & port this proxy is listening to
/// A list of IpAddress & port this proxy is listening to
/// </summary>
/// </summary>
public
static
List
<
ProxyEndPoint
>
ProxyEndPoints
{
get
;
set
;
}
public
List
<
ProxyEndPoint
>
ProxyEndPoints
{
get
;
set
;
}
/// <summary>
/// <summary>
///
Initialize the proxy
///
List of supported Ssl versions
/// </summary>
/// </summary>
public
static
void
Initialize
()
public
SslProtocols
SupportedSslProtocols
{
get
;
set
;
}
=
SslProtocols
.
Tls
|
SslProtocols
.
Tls11
|
SslProtocols
.
Tls12
|
SslProtocols
.
Ssl3
;
{
TcpConnectionManager
.
ClearIdleConnections
();
CertManager
.
ClearIdleCertificates
();
}
/// <summary>
/// <summary>
///
Quit the proxy
///
Constructor
/// </summary>
/// </summary>
public
static
void
Quit
()
public
ProxyServer
()
{
{
TcpConnectionManager
.
StopClearIdleConnections
();
//default values
CertManager
.
StopClearIdleCertificates
();
ConnectionCacheTimeOutMinutes
=
3
;
CertificateCacheTimeOutMinutes
=
60
;
ProxyEndPoints
=
new
List
<
ProxyEndPoint
>();
tcpConnectionCacheManager
=
new
TcpConnectionCacheManager
();
systemProxySettingsManager
=
new
SystemProxyManager
();
firefoxProxySettingsManager
=
new
FireFoxProxySettingsManager
();
RootCertificateName
=
RootCertificateName
??
"Titanium Root Certificate Authority"
;
RootCertificateIssuerName
=
RootCertificateIssuerName
??
"Titanium"
;
certificateCacheManager
=
new
CertificateManager
(
RootCertificateIssuerName
,
RootCertificateName
);
}
}
/// <summary>
/// <summary>
/// Add a proxy end point
/// Add a proxy end point
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
public
static
void
AddEndPoint
(
ProxyEndPoint
endPoint
)
public
void
AddEndPoint
(
ProxyEndPoint
endPoint
)
{
{
if
(
ProxyEndPoints
.
Any
(
x
=>
x
.
IpAddress
==
endPoint
.
IpAddress
&&
x
.
Port
==
endPoint
.
Port
))
throw
new
Exception
(
"Cannot add another endpoint to same port & ip address"
);
ProxyEndPoints
.
Add
(
endPoint
);
ProxyEndPoints
.
Add
(
endPoint
);
if
(
proxyRunning
)
if
(
proxyRunning
)
...
@@ -139,9 +157,8 @@ namespace Titanium.Web.Proxy
...
@@ -139,9 +157,8 @@ namespace Titanium.Web.Proxy
/// Will throw error if the end point does'nt exist
/// Will throw error if the end point does'nt exist
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
public
static
void
RemoveEndPoint
(
ProxyEndPoint
endPoint
)
public
void
RemoveEndPoint
(
ProxyEndPoint
endPoint
)
{
{
if
(
ProxyEndPoints
.
Contains
(
endPoint
)
==
false
)
if
(
ProxyEndPoints
.
Contains
(
endPoint
)
==
false
)
throw
new
Exception
(
"Cannot remove endPoints not added to proxy"
);
throw
new
Exception
(
"Cannot remove endPoints not added to proxy"
);
...
@@ -155,37 +172,30 @@ namespace Titanium.Web.Proxy
...
@@ -155,37 +172,30 @@ namespace Titanium.Web.Proxy
/// Set the given explicit end point as the default proxy server for current machine
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
public
static
void
SetAsSystemHttpProxy
(
ExplicitProxyEndPoint
endPoint
)
public
void
SetAsSystemHttpProxy
(
ExplicitProxyEndPoint
endPoint
)
{
{
ValidateEndPointAsSystemProxy
(
endPoint
);
ValidateEndPointAsSystemProxy
(
endPoint
);
//clear any settings previously added
//clear any settings previously added
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpProxy
=
false
);
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpProxy
=
false
);
SystemProxyHelp
er
.
SetHttpProxy
(
systemProxySettingsManag
er
.
SetHttpProxy
(
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
endPoint
.
Port
);
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
endPoint
.
Port
);
endPoint
.
IsSystemHttpProxy
=
true
;
endPoint
.
IsSystemHttpProxy
=
true
;
#if !DEBUG
#if !DEBUG
FireFoxHelp
er
.
AddFirefox
();
firefoxProxySettingsManag
er
.
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 {1} and port: {2} as System HTTPS Proxy"
,
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
}
}
/// <summary>
/// Remove any HTTP proxy setting of current machien
/// </summary>
public
static
void
DisableSystemHttpProxy
()
{
SystemProxyHelper
.
RemoveHttpProxy
();
}
/// <summary>
/// <summary>
/// Set the given explicit end point as the default proxy server for current machine
/// Set the given explicit end point as the default proxy server for current machine
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
public
static
void
SetAsSystemHttpsProxy
(
ExplicitProxyEndPoint
endPoint
)
public
void
SetAsSystemHttpsProxy
(
ExplicitProxyEndPoint
endPoint
)
{
{
ValidateEndPointAsSystemProxy
(
endPoint
);
ValidateEndPointAsSystemProxy
(
endPoint
);
...
@@ -201,7 +211,7 @@ namespace Titanium.Web.Proxy
...
@@ -201,7 +211,7 @@ namespace Titanium.Web.Proxy
//If certificate was trusted by the machine
//If certificate was trusted by the machine
if
(
certTrusted
)
if
(
certTrusted
)
{
{
SystemProxyHelp
er
.
SetHttpsProxy
(
systemProxySettingsManag
er
.
SetHttpsProxy
(
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
endPoint
.
Port
);
endPoint
.
Port
);
}
}
...
@@ -209,49 +219,52 @@ namespace Titanium.Web.Proxy
...
@@ -209,49 +219,52 @@ namespace Titanium.Web.Proxy
endPoint
.
IsSystemHttpsProxy
=
true
;
endPoint
.
IsSystemHttpsProxy
=
true
;
#if !DEBUG
#if !DEBUG
FireFoxHelp
er
.
AddFirefox
();
firefoxProxySettingsManag
er
.
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 {1} and port: {2} as System HTTPS Proxy"
,
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
}
}
/// <summary>
/// Remove any HTTP proxy setting of current machien
/// </summary>
public
void
DisableSystemHttpProxy
()
{
systemProxySettingsManager
.
RemoveHttpProxy
();
}
/// <summary>
/// <summary>
/// Remove any HTTPS proxy setting for current machine
/// Remove any HTTPS proxy setting for current machine
/// </summary>
/// </summary>
public
static
void
DisableSystemHttpsProxy
()
public
void
DisableSystemHttpsProxy
()
{
{
SystemProxyHelp
er
.
RemoveHttpsProxy
();
systemProxySettingsManag
er
.
RemoveHttpsProxy
();
}
}
/// <summary>
/// <summary>
/// Clear all proxy settings for current machine
/// Clear all proxy settings for current machine
/// </summary>
/// </summary>
public
static
void
DisableAllSystemProxies
()
public
void
DisableAllSystemProxies
()
{
{
SystemProxyHelp
er
.
DisableAllProxy
();
systemProxySettingsManag
er
.
DisableAllProxy
();
}
}
/// <summary>
/// <summary>
/// Start this proxy server
/// Start this proxy server
/// </summary>
/// </summary>
public
static
void
Start
()
public
void
Start
()
{
{
if
(
proxyRunning
)
if
(
proxyRunning
)
throw
new
Exception
(
"Proxy is already running."
);
throw
new
Exception
(
"Proxy is already running."
);
RootCertificateName
=
RootCertificateName
??
"Titanium Root Certificate Authority"
;
certTrusted
=
certificateCacheManager
.
CreateTrustedRootCertificate
().
Result
;
RootCertificateIssuerName
=
RootCertificateIssuerName
??
"Titanium"
;
CertManager
=
new
CertificateManager
(
RootCertificateIssuerName
,
RootCertificateName
);
certTrusted
=
CertManager
.
CreateTrustedRootCertificate
().
Result
;
foreach
(
var
endPoint
in
ProxyEndPoints
)
foreach
(
var
endPoint
in
ProxyEndPoints
)
{
{
Listen
(
endPoint
);
Listen
(
endPoint
);
}
}
Initialize
();
tcpConnectionCacheManager
.
ClearIdleConnections
(
ConnectionCacheTimeOutMinutes
);
certificateCacheManager
.
ClearIdleCertificates
(
CertificateCacheTimeOutMinutes
);
proxyRunning
=
true
;
proxyRunning
=
true
;
}
}
...
@@ -259,7 +272,7 @@ namespace Titanium.Web.Proxy
...
@@ -259,7 +272,7 @@ namespace Titanium.Web.Proxy
/// <summary>
/// <summary>
/// Stop this proxy server
/// Stop this proxy server
/// </summary>
/// </summary>
public
static
void
Stop
()
public
void
Stop
()
{
{
if
(!
proxyRunning
)
if
(!
proxyRunning
)
throw
new
Exception
(
"Proxy is not running."
);
throw
new
Exception
(
"Proxy is not running."
);
...
@@ -268,20 +281,21 @@ namespace Titanium.Web.Proxy
...
@@ -268,20 +281,21 @@ namespace Titanium.Web.Proxy
if
(
setAsSystemProxy
)
if
(
setAsSystemProxy
)
{
{
SystemProxyHelp
er
.
DisableAllProxy
();
systemProxySettingsManag
er
.
DisableAllProxy
();
#if !DEBUG
#if !DEBUG
FireFoxHelp
er
.
RemoveFirefox
();
firefoxProxySettingsManag
er
.
RemoveFirefox
();
#endif
#endif
}
}
foreach
(
var
endPoint
in
ProxyEndPoints
)
foreach
(
var
endPoint
in
ProxyEndPoints
)
{
{
endPoint
.
listener
.
Stop
(
);
QuitListen
(
endPoint
);
}
}
CertManager
.
Dispose
();
ProxyEndPoints
.
Clear
();
Quit
();
tcpConnectionCacheManager
.
StopClearIdleConnections
();
certificateCacheManager
.
StopClearIdleCertificates
();
proxyRunning
=
false
;
proxyRunning
=
false
;
}
}
...
@@ -290,7 +304,7 @@ namespace Titanium.Web.Proxy
...
@@ -290,7 +304,7 @@ namespace Titanium.Web.Proxy
/// Listen on the given end point on local machine
/// Listen on the given end point on local machine
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
private
static
void
Listen
(
ProxyEndPoint
endPoint
)
private
void
Listen
(
ProxyEndPoint
endPoint
)
{
{
endPoint
.
listener
=
new
TcpListener
(
endPoint
.
IpAddress
,
endPoint
.
Port
);
endPoint
.
listener
=
new
TcpListener
(
endPoint
.
IpAddress
,
endPoint
.
Port
);
endPoint
.
listener
.
Start
();
endPoint
.
listener
.
Start
();
...
@@ -304,16 +318,18 @@ namespace Titanium.Web.Proxy
...
@@ -304,16 +318,18 @@ namespace Titanium.Web.Proxy
/// Quit listening on the given end point
/// Quit listening on the given end point
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
private
static
void
QuitListen
(
ProxyEndPoint
endPoint
)
private
void
QuitListen
(
ProxyEndPoint
endPoint
)
{
{
endPoint
.
listener
.
Stop
();
endPoint
.
listener
.
Stop
();
endPoint
.
listener
.
Server
.
Close
();
endPoint
.
listener
.
Server
.
Dispose
();
}
}
/// <summary>
/// <summary>
/// Verifiy if its safe to set this end point as System proxy
/// Verifiy if its safe to set this end point as System proxy
/// </summary>
/// </summary>
/// <param name="endPoint"></param>
/// <param name="endPoint"></param>
private
static
void
ValidateEndPointAsSystemProxy
(
ExplicitProxyEndPoint
endPoint
)
private
void
ValidateEndPointAsSystemProxy
(
ExplicitProxyEndPoint
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"
);
...
@@ -326,7 +342,7 @@ namespace Titanium.Web.Proxy
...
@@ -326,7 +342,7 @@ namespace Titanium.Web.Proxy
/// When a connection is received from client act
/// When a connection is received from client act
/// </summary>
/// </summary>
/// <param name="asyn"></param>
/// <param name="asyn"></param>
private
static
void
OnAcceptConnection
(
IAsyncResult
asyn
)
private
void
OnAcceptConnection
(
IAsyncResult
asyn
)
{
{
var
endPoint
=
(
ProxyEndPoint
)
asyn
.
AsyncState
;
var
endPoint
=
(
ProxyEndPoint
)
asyn
.
AsyncState
;
...
@@ -353,8 +369,15 @@ namespace Titanium.Web.Proxy
...
@@ -353,8 +369,15 @@ namespace Titanium.Web.Proxy
{
{
//Other errors are discarded to keep proxy running
//Other errors are discarded to keep proxy running
}
}
}
public
void
Dispose
()
{
if
(
proxyRunning
)
Stop
();
certificateCacheManager
.
Dispose
();
}
}
}
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/RequestHandler.cs
View file @
a954c575
...
@@ -13,8 +13,8 @@ using Titanium.Web.Proxy.Models;
...
@@ -13,8 +13,8 @@ using Titanium.Web.Proxy.Models;
using
System.Security.Cryptography.X509Certificates
;
using
System.Security.Cryptography.X509Certificates
;
using
Titanium.Web.Proxy.Shared
;
using
Titanium.Web.Proxy.Shared
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Extensions
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
namespace
Titanium.Web.Proxy
namespace
Titanium.Web.Proxy
{
{
...
@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy
...
@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy
partial
class
ProxyServer
partial
class
ProxyServer
{
{
//This is called when client is aware of proxy
//This is called when client is aware of proxy
private
static
async
void
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
client
)
private
async
void
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
client
)
{
{
Stream
clientStream
=
client
.
GetStream
();
Stream
clientStream
=
client
.
GetStream
();
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
);
...
@@ -64,8 +64,8 @@ namespace Titanium.Web.Proxy
...
@@ -64,8 +64,8 @@ namespace Titanium.Web.Proxy
version
=
new
Version
(
1
,
0
);
version
=
new
Version
(
1
,
0
);
}
}
}
}
//filter out excluded host names
var
excluded
=
endPoint
.
ExcludedHttpsHostNameRegex
!=
null
?
var
excluded
=
endPoint
.
ExcludedHttpsHostNameRegex
!=
null
?
endPoint
.
ExcludedHttpsHostNameRegex
.
Any
(
x
=>
Regex
.
IsMatch
(
httpRemoteUri
.
Host
,
x
))
:
false
;
endPoint
.
ExcludedHttpsHostNameRegex
.
Any
(
x
=>
Regex
.
IsMatch
(
httpRemoteUri
.
Host
,
x
))
:
false
;
//Client wants to create a secure tcp tunnel (its a HTTPS request)
//Client wants to create a secure tcp tunnel (its a HTTPS request)
...
@@ -82,14 +82,17 @@ namespace Titanium.Web.Proxy
...
@@ -82,14 +82,17 @@ namespace Titanium.Web.Proxy
{
{
//create the Tcp Connection to server and then release it to connection cache
//create the Tcp Connection to server and then release it to connection cache
//Just doing what CONNECT request is asking as to do
//Just doing what CONNECT request is asking as to do
var
tunnelClient
=
await
TcpConnectionManager
.
GetClient
(
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
true
,
version
);
var
tunnelClient
=
await
tcpConnectionCacheManager
.
GetClient
(
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
true
,
version
,
await
TcpConnectionManager
.
ReleaseClient
(
tunnelClient
);
UpStreamHttpProxy
,
UpStreamHttpsProxy
,
BUFFER_SIZE
,
SupportedSslProtocols
,
new
RemoteCertificateValidationCallback
(
ValidateServerCertificate
),
new
LocalCertificateSelectionCallback
(
SelectClientCertificate
));
await
tcpConnectionCacheManager
.
ReleaseClient
(
tunnelClient
);
sslStream
=
new
SslStream
(
clientStream
,
true
);
sslStream
=
new
SslStream
(
clientStream
,
true
);
var
certificate
=
await
Cert
Manager
.
CreateCertificate
(
httpRemoteUri
.
Host
,
false
);
var
certificate
=
await
certificateCache
Manager
.
CreateCertificate
(
httpRemoteUri
.
Host
,
false
);
//Successfully managed to authenticate the client using the fake certificate
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
ProxyConstants
.
SupportedSslProtocols
,
false
);
SupportedSslProtocols
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
sslStream
;
clientStream
=
sslStream
;
...
@@ -120,7 +123,7 @@ namespace Titanium.Web.Proxy
...
@@ -120,7 +123,7 @@ namespace Titanium.Web.Proxy
//Just relay the request/response without decrypting it
//Just relay the request/response without decrypting it
await
TcpHelper
.
SendRaw
(
clientStream
,
null
,
null
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
await
TcpHelper
.
SendRaw
(
clientStream
,
null
,
null
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
false
);
false
,
SupportedSslProtocols
);
Dispose
(
client
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
Dispose
(
client
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
return
;
...
@@ -138,7 +141,7 @@ namespace Titanium.Web.Proxy
...
@@ -138,7 +141,7 @@ namespace Titanium.Web.Proxy
//This is called when requests are routed through router to this endpoint
//This is called when requests are routed through router to this endpoint
//For ssl requests
//For ssl requests
private
static
async
void
HandleClient
(
TransparentProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
private
async
void
HandleClient
(
TransparentProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
{
Stream
clientStream
=
tcpClient
.
GetStream
();
Stream
clientStream
=
tcpClient
.
GetStream
();
CustomBinaryReader
clientStreamReader
=
null
;
CustomBinaryReader
clientStreamReader
=
null
;
...
@@ -148,13 +151,9 @@ namespace Titanium.Web.Proxy
...
@@ -148,13 +151,9 @@ namespace Titanium.Web.Proxy
if
(
endPoint
.
EnableSsl
)
if
(
endPoint
.
EnableSsl
)
{
{
var
sslStream
=
new
SslStream
(
clientStream
,
true
);
var
sslStream
=
new
SslStream
(
clientStream
,
true
);
//if(endPoint.UseServerNameIndication)
//{
//implement in future once SNI supported by SSL stream, for now use the same certificate
// //implement in future once SNI supported by SSL stream
certificate
=
await
certificateCacheManager
.
CreateCertificate
(
endPoint
.
GenericCertificateName
,
false
);
// certificate = CertManager.CreateCertificate(hostName);
//}
//else
certificate
=
await
CertManager
.
CreateCertificate
(
endPoint
.
GenericCertificateName
,
false
);
try
try
{
{
...
@@ -182,6 +181,7 @@ namespace Titanium.Web.Proxy
...
@@ -182,6 +181,7 @@ namespace Titanium.Web.Proxy
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
);
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
);
}
}
//now read the request line
var
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
var
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
//Now create the request
//Now create the request
...
@@ -198,10 +198,10 @@ namespace Titanium.Web.Proxy
...
@@ -198,10 +198,10 @@ namespace Titanium.Web.Proxy
/// <param name="clientStreamWriter"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="isHttps"></param>
/// <param name="isHttps"></param>
/// <returns></returns>
/// <returns></returns>
private
static
async
Task
HandleHttpSessionRequest
(
TcpClient
client
,
string
httpCmd
,
Stream
clientStream
,
private
async
Task
HandleHttpSessionRequest
(
TcpClient
client
,
string
httpCmd
,
Stream
clientStream
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
bool
isHttps
)
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
bool
isHttps
)
{
{
TcpConnection
connection
=
null
;
TcpConnection
Cache
connection
=
null
;
//Loop through each subsequest request on this particular client connection
//Loop through each subsequest request on this particular client connection
//(assuming HTTP connection is kept alive by client)
//(assuming HTTP connection is kept alive by client)
...
@@ -213,7 +213,7 @@ namespace Titanium.Web.Proxy
...
@@ -213,7 +213,7 @@ namespace Titanium.Web.Proxy
break
;
break
;
}
}
var
args
=
new
SessionEventArgs
();
var
args
=
new
SessionEventArgs
(
BUFFER_SIZE
,
HandleHttpSessionResponse
);
args
.
ProxyClient
.
TcpClient
=
client
;
args
.
ProxyClient
.
TcpClient
=
client
;
try
try
...
@@ -284,13 +284,15 @@ namespace Titanium.Web.Proxy
...
@@ -284,13 +284,15 @@ namespace Titanium.Web.Proxy
if
(
args
.
WebSession
.
Request
.
UpgradeToWebSocket
)
if
(
args
.
WebSession
.
Request
.
UpgradeToWebSocket
)
{
{
await
TcpHelper
.
SendRaw
(
clientStream
,
httpCmd
,
args
.
WebSession
.
Request
.
RequestHeaders
,
await
TcpHelper
.
SendRaw
(
clientStream
,
httpCmd
,
args
.
WebSession
.
Request
.
RequestHeaders
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
args
.
IsHttps
);
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
args
.
IsHttps
,
SupportedSslProtocols
);
Dispose
(
client
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
args
);
Dispose
(
client
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
args
);
return
;
return
;
}
}
//construct the web request that we are going to issue on behalf of the client.
//construct the web request that we are going to issue on behalf of the client.
connection
=
await
TcpConnectionManager
.
GetClient
(
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
args
.
WebSession
.
Request
.
RequestUri
.
Port
,
args
.
IsHttps
,
version
);
connection
=
await
tcpConnectionCacheManager
.
GetClient
(
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
args
.
WebSession
.
Request
.
RequestUri
.
Port
,
args
.
IsHttps
,
version
,
UpStreamHttpProxy
,
UpStreamHttpsProxy
,
BUFFER_SIZE
,
SupportedSslProtocols
,
new
RemoteCertificateValidationCallback
(
ValidateServerCertificate
),
new
LocalCertificateSelectionCallback
(
SelectClientCertificate
));
args
.
WebSession
.
Request
.
RequestLocked
=
true
;
args
.
WebSession
.
Request
.
RequestLocked
=
true
;
...
@@ -306,7 +308,7 @@ namespace Titanium.Web.Proxy
...
@@ -306,7 +308,7 @@ namespace Titanium.Web.Proxy
if
(
args
.
WebSession
.
Request
.
ExpectContinue
)
if
(
args
.
WebSession
.
Request
.
ExpectContinue
)
{
{
args
.
WebSession
.
SetConnection
(
connection
);
args
.
WebSession
.
SetConnection
(
connection
);
await
args
.
WebSession
.
SendRequest
();
await
args
.
WebSession
.
SendRequest
(
Enable100ContinueBehaviour
);
}
}
//If 100 continue was the response inform that to the client
//If 100 continue was the response inform that to the client
...
@@ -328,7 +330,7 @@ namespace Titanium.Web.Proxy
...
@@ -328,7 +330,7 @@ namespace Titanium.Web.Proxy
if
(!
args
.
WebSession
.
Request
.
ExpectContinue
)
if
(!
args
.
WebSession
.
Request
.
ExpectContinue
)
{
{
args
.
WebSession
.
SetConnection
(
connection
);
args
.
WebSession
.
SetConnection
(
connection
);
await
args
.
WebSession
.
SendRequest
();
await
args
.
WebSession
.
SendRequest
(
Enable100ContinueBehaviour
);
}
}
//If request was modified by user
//If request was modified by user
...
@@ -370,7 +372,7 @@ namespace Titanium.Web.Proxy
...
@@ -370,7 +372,7 @@ namespace Titanium.Web.Proxy
}
}
//send the tcp connection to server back to connection cache for reuse
//send the tcp connection to server back to connection cache for reuse
await
TcpConnection
Manager
.
ReleaseClient
(
connection
);
await
tcpConnectionCache
Manager
.
ReleaseClient
(
connection
);
// read the next request
// read the next request
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
...
@@ -392,7 +394,7 @@ namespace Titanium.Web.Proxy
...
@@ -392,7 +394,7 @@ namespace Titanium.Web.Proxy
/// <param name="clientStreamWriter"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="httpVersion"></param>
/// <param name="httpVersion"></param>
/// <returns></returns>
/// <returns></returns>
private
static
async
Task
WriteConnectResponse
(
StreamWriter
clientStreamWriter
,
Version
httpVersion
)
private
async
Task
WriteConnectResponse
(
StreamWriter
clientStreamWriter
,
Version
httpVersion
)
{
{
await
clientStreamWriter
.
WriteLineAsync
(
string
.
Format
(
"HTTP/{0}.{1} {2}"
,
httpVersion
.
Major
,
httpVersion
.
Minor
,
"200 Connection established"
));
await
clientStreamWriter
.
WriteLineAsync
(
string
.
Format
(
"HTTP/{0}.{1} {2}"
,
httpVersion
.
Major
,
httpVersion
.
Minor
,
"200 Connection established"
));
await
clientStreamWriter
.
WriteLineAsync
(
string
.
Format
(
"Timestamp: {0}"
,
DateTime
.
Now
));
await
clientStreamWriter
.
WriteLineAsync
(
string
.
Format
(
"Timestamp: {0}"
,
DateTime
.
Now
));
...
@@ -405,12 +407,13 @@ namespace Titanium.Web.Proxy
...
@@ -405,12 +407,13 @@ namespace Titanium.Web.Proxy
/// </summary>
/// </summary>
/// <param name="requestHeaders"></param>
/// <param name="requestHeaders"></param>
/// <param name="webRequest"></param>
/// <param name="webRequest"></param>
private
static
void
PrepareRequestHeaders
(
List
<
HttpHeader
>
requestHeaders
,
HttpWebClient
webRequest
)
private
void
PrepareRequestHeaders
(
List
<
HttpHeader
>
requestHeaders
,
HttpWebClient
webRequest
)
{
{
for
(
var
i
=
0
;
i
<
requestHeaders
.
Count
;
i
++)
for
(
var
i
=
0
;
i
<
requestHeaders
.
Count
;
i
++)
{
{
switch
(
requestHeaders
[
i
].
Name
.
ToLower
())
switch
(
requestHeaders
[
i
].
Name
.
ToLower
())
{
{
//these are the only encoding this proxy can read
case
"accept-encoding"
:
case
"accept-encoding"
:
requestHeaders
[
i
].
Value
=
"gzip,deflate,zlib"
;
requestHeaders
[
i
].
Value
=
"gzip,deflate,zlib"
;
break
;
break
;
...
@@ -428,7 +431,7 @@ namespace Titanium.Web.Proxy
...
@@ -428,7 +431,7 @@ namespace Titanium.Web.Proxy
/// Fix proxy specific headers
/// Fix proxy specific headers
/// </summary>
/// </summary>
/// <param name="headers"></param>
/// <param name="headers"></param>
private
static
void
FixRequestProxyHeaders
(
List
<
HttpHeader
>
headers
)
private
void
FixRequestProxyHeaders
(
List
<
HttpHeader
>
headers
)
{
{
//If proxy-connection close was returned inform to close the connection
//If proxy-connection close was returned inform to close the connection
var
proxyHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
var
proxyHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
...
@@ -452,33 +455,23 @@ namespace Titanium.Web.Proxy
...
@@ -452,33 +455,23 @@ namespace Titanium.Web.Proxy
/// </summary>
/// </summary>
/// <param name="args"></param>
/// <param name="args"></param>
/// <returns></returns>
/// <returns></returns>
private
static
async
Task
SendClientRequestBody
(
SessionEventArgs
args
)
private
async
Task
SendClientRequestBody
(
SessionEventArgs
args
)
{
{
// End the operation
// End the operation
var
postStream
=
args
.
WebSession
.
ServerConnection
.
Stream
;
var
postStream
=
args
.
WebSession
.
ServerConnection
.
Stream
;
//send the request body bytes to server
if
(
args
.
WebSession
.
Request
.
ContentLength
>
0
)
if
(
args
.
WebSession
.
Request
.
ContentLength
>
0
)
{
{
try
await
args
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
BUFFER_SIZE
,
postStream
,
args
.
WebSession
.
Request
.
ContentLength
);
{
await
args
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
postStream
,
args
.
WebSession
.
Request
.
ContentLength
);
}
catch
{
throw
;
}
}
}
//Need to revist, find any potential bugs
//Need to revist, find any potential bugs
//send the request body bytes to server in chunks
else
if
(
args
.
WebSession
.
Request
.
IsChunked
)
else
if
(
args
.
WebSession
.
Request
.
IsChunked
)
{
{
try
await
args
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStreamChunked
(
BUFFER_SIZE
,
postStream
);
{
await
args
.
ProxyClient
.
ClientStreamReader
.
CopyBytesToStreamChunked
(
postStream
);
}
catch
{
throw
;
}
}
}
}
}
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
a954c575
...
@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy
...
@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy
partial
class
ProxyServer
partial
class
ProxyServer
{
{
//Called asynchronously when a request was successfully and we received the response
//Called asynchronously when a request was successfully and we received the response
public
static
async
Task
HandleHttpSessionResponse
(
SessionEventArgs
args
)
public
async
Task
HandleHttpSessionResponse
(
SessionEventArgs
args
)
{
{
//read response & headers from server
//read response & headers from server
await
args
.
WebSession
.
ReceiveResponse
();
await
args
.
WebSession
.
ReceiveResponse
();
...
@@ -83,9 +83,14 @@ namespace Titanium.Web.Proxy
...
@@ -83,9 +83,14 @@ namespace Titanium.Web.Proxy
{
{
await
WriteResponseHeaders
(
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
Response
.
ResponseHeaders
);
await
WriteResponseHeaders
(
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
Response
.
ResponseHeaders
);
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
||
//Write body only if response is chunked or content length >0
(
args
.
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
args
.
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
))
//Is none are true then check if connection:close header exist, if so write response until server or client terminates the connection
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
||
!
args
.
WebSession
.
Response
.
ResponseKeepAlive
)
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BUFFER_SIZE
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
//write response if connection:keep-alive header exist and when version is http/1.0
//Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream)
else
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
&&
args
.
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BUFFER_SIZE
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
}
}
await
args
.
ProxyClient
.
ClientStream
.
FlushAsync
();
await
args
.
ProxyClient
.
ClientStream
.
FlushAsync
();
...
@@ -107,7 +112,7 @@ namespace Titanium.Web.Proxy
...
@@ -107,7 +112,7 @@ namespace Titanium.Web.Proxy
/// <param name="encodingType"></param>
/// <param name="encodingType"></param>
/// <param name="responseBodyStream"></param>
/// <param name="responseBodyStream"></param>
/// <returns></returns>
/// <returns></returns>
private
static
async
Task
<
byte
[
]>
GetCompressedResponseBody
(
string
encodingType
,
byte
[]
responseBodyStream
)
private
async
Task
<
byte
[
]>
GetCompressedResponseBody
(
string
encodingType
,
byte
[]
responseBodyStream
)
{
{
var
compressionFactory
=
new
CompressionFactory
();
var
compressionFactory
=
new
CompressionFactory
();
var
compressor
=
compressionFactory
.
Create
(
encodingType
);
var
compressor
=
compressionFactory
.
Create
(
encodingType
);
...
@@ -122,7 +127,7 @@ namespace Titanium.Web.Proxy
...
@@ -122,7 +127,7 @@ namespace Titanium.Web.Proxy
/// <param name="description"></param>
/// <param name="description"></param>
/// <param name="responseWriter"></param>
/// <param name="responseWriter"></param>
/// <returns></returns>
/// <returns></returns>
private
static
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
(
string
.
Format
(
"HTTP/{0}.{1} {2} {3}"
,
version
.
Major
,
version
.
Minor
,
code
,
description
));
...
@@ -134,7 +139,7 @@ namespace Titanium.Web.Proxy
...
@@ -134,7 +139,7 @@ namespace Titanium.Web.Proxy
/// <param name="responseWriter"></param>
/// <param name="responseWriter"></param>
/// <param name="headers"></param>
/// <param name="headers"></param>
/// <returns></returns>
/// <returns></returns>
private
static
async
Task
WriteResponseHeaders
(
StreamWriter
responseWriter
,
List
<
HttpHeader
>
headers
)
private
async
Task
WriteResponseHeaders
(
StreamWriter
responseWriter
,
List
<
HttpHeader
>
headers
)
{
{
if
(
headers
!=
null
)
if
(
headers
!=
null
)
{
{
...
@@ -154,7 +159,7 @@ namespace Titanium.Web.Proxy
...
@@ -154,7 +159,7 @@ namespace Titanium.Web.Proxy
/// Fix the proxy specific headers before sending response headers to client
/// Fix the proxy specific headers before sending response headers to client
/// </summary>
/// </summary>
/// <param name="headers"></param>
/// <param name="headers"></param>
private
static
void
FixResponseProxyHeaders
(
List
<
HttpHeader
>
headers
)
private
void
FixResponseProxyHeaders
(
List
<
HttpHeader
>
headers
)
{
{
//If proxy-connection close was returned inform to close the connection
//If proxy-connection close was returned inform to close the connection
var
proxyHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
var
proxyHeader
=
headers
.
FirstOrDefault
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
...
@@ -172,7 +177,7 @@ namespace Titanium.Web.Proxy
...
@@ -172,7 +177,7 @@ namespace Titanium.Web.Proxy
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
headers
.
RemoveAll
(
x
=>
x
.
Name
.
ToLower
()
==
"proxy-connection"
);
}
}
/// <summary>
/// <summary>
/// Handle dispose of a client/server session
/// Handle dispose of a client/server session
/// </summary>
/// </summary>
...
@@ -181,7 +186,7 @@ namespace Titanium.Web.Proxy
...
@@ -181,7 +186,7 @@ namespace Titanium.Web.Proxy
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="args"></param>
/// <param name="args"></param>
private
static
void
Dispose
(
TcpClient
client
,
IDisposable
clientStream
,
IDisposable
clientStreamReader
,
private
void
Dispose
(
TcpClient
client
,
IDisposable
clientStream
,
IDisposable
clientStreamReader
,
IDisposable
clientStreamWriter
,
IDisposable
args
)
IDisposable
clientStreamWriter
,
IDisposable
args
)
{
{
if
(
args
!=
null
)
if
(
args
!=
null
)
...
...
Titanium.Web.Proxy/Shared/ProxyConstants.cs
View file @
a954c575
using
System
;
using
System
;
using
System.Security.Authentication
;
using
System.Text
;
using
System.Text
;
namespace
Titanium.Web.Proxy.Shared
namespace
Titanium.Web.Proxy.Shared
...
@@ -9,7 +8,7 @@ namespace Titanium.Web.Proxy.Shared
...
@@ -9,7 +8,7 @@ namespace Titanium.Web.Proxy.Shared
/// </summary>
/// </summary>
internal
class
ProxyConstants
internal
class
ProxyConstants
{
{
internal
static
readonly
char
[]
SpaceSplit
=
{
' '
};
internal
static
readonly
char
[]
SpaceSplit
=
{
' '
};
internal
static
readonly
char
[]
ColonSplit
=
{
':'
};
internal
static
readonly
char
[]
ColonSplit
=
{
':'
};
internal
static
readonly
char
[]
SemiColonSplit
=
{
';'
};
internal
static
readonly
char
[]
SemiColonSplit
=
{
';'
};
...
@@ -18,8 +17,5 @@ namespace Titanium.Web.Proxy.Shared
...
@@ -18,8 +17,5 @@ namespace Titanium.Web.Proxy.Shared
internal
static
readonly
byte
[]
ChunkEnd
=
internal
static
readonly
byte
[]
ChunkEnd
=
Encoding
.
ASCII
.
GetBytes
(
0.
ToString
(
"x2"
)
+
Environment
.
NewLine
+
Environment
.
NewLine
);
Encoding
.
ASCII
.
GetBytes
(
0.
ToString
(
"x2"
)
+
Environment
.
NewLine
+
Environment
.
NewLine
);
public
static
SslProtocols
SupportedSslProtocols
=
SslProtocols
.
Tls
|
SslProtocols
.
Tls11
|
SslProtocols
.
Tls12
|
SslProtocols
.
Ssl3
;
public
static
readonly
int
BUFFER_SIZE
=
8192
;
}
}
}
}
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
a954c575
...
@@ -77,8 +77,8 @@
...
@@ -77,8 +77,8 @@
<Compile
Include=
"Http\Request.cs"
/>
<Compile
Include=
"Http\Request.cs"
/>
<Compile
Include=
"Http\Response.cs"
/>
<Compile
Include=
"Http\Response.cs"
/>
<Compile
Include=
"Models\ExternalProxy.cs"
/>
<Compile
Include=
"Models\ExternalProxy.cs"
/>
<Compile
Include=
"Network\TcpConnection.cs"
/>
<Compile
Include=
"Network\TcpConnection
Cache
.cs"
/>
<Compile
Include=
"Network\TcpConnectionManager.cs"
/>
<Compile
Include=
"Network\TcpConnection
Cache
Manager.cs"
/>
<Compile
Include=
"Models\HttpHeader.cs"
/>
<Compile
Include=
"Models\HttpHeader.cs"
/>
<Compile
Include=
"Http\HttpWebClient.cs"
/>
<Compile
Include=
"Http\HttpWebClient.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment