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
4b86cde8
Commit
4b86cde8
authored
May 20, 2016
by
justcoding121
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
asyncify more
parent
ff0dddf4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
340 additions
and
294 deletions
+340
-294
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+24
-26
README.md
README.md
+30
-26
DeflateCompression.cs
Titanium.Web.Proxy/Compression/DeflateCompression.cs
+3
-2
GZipCompression.cs
Titanium.Web.Proxy/Compression/GZipCompression.cs
+3
-2
ICompression.cs
Titanium.Web.Proxy/Compression/ICompression.cs
+4
-2
ZlibCompression.cs
Titanium.Web.Proxy/Compression/ZlibCompression.cs
+3
-2
DefaultDecompression.cs
Titanium.Web.Proxy/Decompression/DefaultDecompression.cs
+5
-3
DeflateDecompression.cs
Titanium.Web.Proxy/Decompression/DeflateDecompression.cs
+4
-3
GZipDecompression.cs
Titanium.Web.Proxy/Decompression/GZipDecompression.cs
+4
-3
IDecompression.cs
Titanium.Web.Proxy/Decompression/IDecompression.cs
+2
-1
ZlibDecompression.cs
Titanium.Web.Proxy/Decompression/ZlibDecompression.cs
+4
-3
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+36
-35
StreamExtensions.cs
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
+10
-10
CustomBinaryReader.cs
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
+8
-7
Tcp.cs
Titanium.Web.Proxy/Helpers/Tcp.cs
+11
-11
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+14
-13
TcpConnectionManager.cs
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
+18
-16
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+5
-50
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+103
-39
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+49
-40
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
4b86cde8
...
...
@@ -2,6 +2,7 @@
using
System.Collections.Generic
;
using
System.Net
;
using
System.Text.RegularExpressions
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
...
...
@@ -13,7 +14,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
ProxyServer
.
BeforeRequest
+=
OnRequest
;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
ProxyServer
.
Remote
CertificateValidationCallback
+=
OnCertificateValidation
;
ProxyServer
.
Server
CertificateValidationCallback
+=
OnCertificateValidation
;
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
...
...
@@ -61,9 +62,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
ProxyServer
.
Stop
();
}
//Test On Request, intecept requests
//Read browser URL send back to proxy by the injection script in OnResponse event
public
void
OnRequest
(
object
sender
,
SessionEventArgs
e
)
//intecept & cancel, redirect or update requests
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
Console
.
WriteLine
(
e
.
WebSession
.
Request
.
Url
);
...
...
@@ -73,12 +73,12 @@ namespace Titanium.Web.Proxy.Examples.Basic
if
((
e
.
WebSession
.
Request
.
Method
.
ToUpper
()
==
"POST"
||
e
.
WebSession
.
Request
.
Method
.
ToUpper
()
==
"PUT"
))
{
//Get/Set request body bytes
byte
[]
bodyBytes
=
e
.
GetRequestBody
();
e
.
SetRequestBody
(
bodyBytes
);
byte
[]
bodyBytes
=
await
e
.
GetRequestBody
();
await
e
.
SetRequestBody
(
bodyBytes
);
//Get/Set request body as string
string
bodyString
=
e
.
GetRequestBodyAsString
();
e
.
SetRequestBodyString
(
bodyString
);
string
bodyString
=
await
e
.
GetRequestBodyAsString
();
await
e
.
SetRequestBodyString
(
bodyString
);
}
...
...
@@ -86,26 +86,24 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Filter URL
if
(
e
.
WebSession
.
Request
.
RequestUri
.
AbsoluteUri
.
Contains
(
"google.com"
))
{
e
.
Ok
(
"<!DOCTYPE html>"
+
"<html><body><h1>"
+
"Website Blocked"
+
"</h1>"
+
"<p>Blocked by titanium web proxy.</p>"
+
"</body>"
+
"</html>"
);
await
e
.
Ok
(
"<!DOCTYPE html>"
+
"<html><body><h1>"
+
"Website Blocked"
+
"</h1>"
+
"<p>Blocked by titanium web proxy.</p>"
+
"</body>"
+
"</html>"
);
}
//Redirect example
if
(
e
.
WebSession
.
Request
.
RequestUri
.
AbsoluteUri
.
Contains
(
"wikipedia.org"
))
{
e
.
Redirect
(
"https://www.paypal.com"
);
await
e
.
Redirect
(
"https://www.paypal.com"
);
}
}
//Test script injection
//Insert script to read the Browser URL and send it back to proxy
public
void
OnResponse
(
object
sender
,
SessionEventArgs
e
)
//Modify response
public
async
Task
OnResponse
(
object
sender
,
SessionEventArgs
e
)
{
//read response headers
var
responseHeaders
=
e
.
WebSession
.
Response
.
ResponseHeaders
;
...
...
@@ -116,11 +114,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
if
(
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
{
byte
[]
bodyBytes
=
e
.
GetResponseBody
();
e
.
SetResponseBody
(
bodyBytes
);
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
await
e
.
SetResponseBody
(
bodyBytes
);
string
body
=
e
.
GetResponseBodyAsString
();
e
.
SetResponseBodyString
(
body
);
string
body
=
await
e
.
GetResponseBodyAsString
();
await
e
.
SetResponseBodyString
(
body
);
}
}
}
...
...
@@ -131,13 +129,13 @@ namespace Titanium.Web.Proxy.Examples.Basic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public
void
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
public
async
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
//set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
System
.
Net
.
Security
.
SslPolicyErrors
.
None
)
e
.
IsValid
=
true
;
else
e
.
Session
.
Ok
(
"Cannot validate server certificate! Not safe to proceed."
);
await
e
.
Session
.
Ok
(
"Cannot validate server certificate! Not safe to proceed."
);
}
}
}
\ No newline at end of file
README.md
View file @
4b86cde8
...
...
@@ -34,7 +34,7 @@ Setup HTTP proxy:
```
csharp
ProxyServer
.
BeforeRequest
+=
OnRequest
;
ProxyServer
.
BeforeResponse
+=
OnResponse
;
ProxyServer
.
Remote
CertificateValidationCallback
+=
OnCertificateValidation
;
ProxyServer
.
Server
CertificateValidationCallback
+=
OnCertificateValidation
;
//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
...
...
@@ -61,8 +61,7 @@ Setup HTTP proxy:
GenericCertificateName
=
"google.com"
};
ProxyServer
.
AddEndPoint
(
transparentEndPoint
);
//ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
...
...
@@ -87,7 +86,8 @@ Sample request and response event handlers
```
csharp
public
void
OnRequest
(
object
sender
,
SessionEventArgs
e
)
//intecept & cancel, redirect or update requests
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
Console
.
WriteLine
(
e
.
WebSession
.
Request
.
Url
);
...
...
@@ -97,12 +97,12 @@ Sample request and response event handlers
if
((
e
.
WebSession
.
Request
.
Method
.
ToUpper
()
==
"POST"
||
e
.
WebSession
.
Request
.
Method
.
ToUpper
()
==
"PUT"
))
{
//Get/Set request body bytes
byte
[]
bodyBytes
=
e
.
GetRequestBody
();
e
.
SetRequestBody
(
bodyBytes
);
byte
[]
bodyBytes
=
await
e
.
GetRequestBody
();
await
e
.
SetRequestBody
(
bodyBytes
);
//Get/Set request body as string
string
bodyString
=
e
.
GetRequestBodyAsString
();
e
.
SetRequestBodyString
(
bodyString
);
string
bodyString
=
await
e
.
GetRequestBodyAsString
();
await
e
.
SetRequestBodyString
(
bodyString
);
}
...
...
@@ -110,24 +110,24 @@ Sample request and response event handlers
//Filter URL
if
(
e
.
WebSession
.
Request
.
RequestUri
.
AbsoluteUri
.
Contains
(
"google.com"
))
{
e
.
Ok
(
"<!DOCTYPE html>"
+
"<html><body><h1>"
+
"Website Blocked"
+
"</h1>"
+
"<p>Blocked by titanium web proxy.</p>"
+
"</body>"
+
"</html>"
);
await
e
.
Ok
(
"<!DOCTYPE html>"
+
"<html><body><h1>"
+
"Website Blocked"
+
"</h1>"
+
"<p>Blocked by titanium web proxy.</p>"
+
"</body>"
+
"</html>"
);
}
//Redirect example
if
(
e
.
WebSession
.
Request
.
RequestUri
.
AbsoluteUri
.
Contains
(
"wikipedia.org"
))
{
e
.
Redirect
(
"https://www.paypal.com"
);
await
e
.
Redirect
(
"https://www.paypal.com"
);
}
}
public
void
OnResponse
(
object
sender
,
SessionEventArgs
e
)
{
//Modify response
public
async
Task
OnResponse
(
object
sender
,
SessionEventArgs
e
)
{
//read response headers
var
responseHeaders
=
e
.
WebSession
.
Response
.
ResponseHeaders
;
...
...
@@ -138,24 +138,28 @@ Sample request and response event handlers
{
if
(
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
{
byte
[]
bodyBytes
=
e
.
GetResponseBody
();
e
.
SetResponseBody
(
bodyBytes
);
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
await
e
.
SetResponseBody
(
bodyBytes
);
string
body
=
e
.
GetResponseBodyAsString
();
e
.
SetResponseBodyString
(
body
);
string
body
=
await
e
.
GetResponseBodyAsString
();
await
e
.
SetResponseBodyString
(
body
);
}
}
}
}
// Allows overriding default certificate validation logic
public
void
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
/// <summary>
/// Allows overriding default certificate validation logic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public
async
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
//set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
System
.
Net
.
Security
.
SslPolicyErrors
.
None
)
e
.
IsValid
=
true
;
else
e
.
Session
.
Ok
(
"Cannot validate server certificate! Not safe to proceed."
);
await
e
.
Session
.
Ok
(
"Cannot validate server certificate! Not safe to proceed."
);
}
```
Future roadmap
...
...
Titanium.Web.Proxy/Compression/DeflateCompression.cs
View file @
4b86cde8
using
System.IO
;
using
System.IO.Compression
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Compression
{
class
DeflateCompression
:
ICompression
{
public
byte
[]
Compress
(
byte
[]
responseBody
)
public
async
Task
<
byte
[
]>
Compress
(
byte
[]
responseBody
)
{
using
(
var
ms
=
new
MemoryStream
())
{
using
(
var
zip
=
new
DeflateStream
(
ms
,
CompressionMode
.
Compress
,
true
))
{
zip
.
Write
(
responseBody
,
0
,
responseBody
.
Length
);
await
zip
.
WriteAsync
(
responseBody
,
0
,
responseBody
.
Length
).
ConfigureAwait
(
false
);
}
return
ms
.
ToArray
();
...
...
Titanium.Web.Proxy/Compression/GZipCompression.cs
View file @
4b86cde8
using
Ionic.Zlib
;
using
System.IO
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Compression
{
class
GZipCompression
:
ICompression
{
public
byte
[]
Compress
(
byte
[]
responseBody
)
public
async
Task
<
byte
[
]>
Compress
(
byte
[]
responseBody
)
{
using
(
var
ms
=
new
MemoryStream
())
{
using
(
var
zip
=
new
GZipStream
(
ms
,
CompressionMode
.
Compress
,
true
))
{
zip
.
Write
(
responseBody
,
0
,
responseBody
.
Length
);
await
zip
.
WriteAsync
(
responseBody
,
0
,
responseBody
.
Length
).
ConfigureAwait
(
false
);
}
return
ms
.
ToArray
();
...
...
Titanium.Web.Proxy/Compression/ICompression.cs
View file @
4b86cde8
namespace
Titanium.Web.Proxy.Compression
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Compression
{
interface
ICompression
{
byte
[]
Compress
(
byte
[]
responseBody
);
Task
<
byte
[
]>
Compress
(
byte
[]
responseBody
);
}
}
Titanium.Web.Proxy/Compression/ZlibCompression.cs
View file @
4b86cde8
using
Ionic.Zlib
;
using
System.IO
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Compression
{
class
ZlibCompression
:
ICompression
{
public
byte
[]
Compress
(
byte
[]
responseBody
)
public
async
Task
<
byte
[
]>
Compress
(
byte
[]
responseBody
)
{
using
(
var
ms
=
new
MemoryStream
())
{
using
(
var
zip
=
new
ZlibStream
(
ms
,
CompressionMode
.
Compress
,
true
))
{
zip
.
Write
(
responseBody
,
0
,
responseBody
.
Length
);
await
zip
.
WriteAsync
(
responseBody
,
0
,
responseBody
.
Length
).
ConfigureAwait
(
false
);
}
return
ms
.
ToArray
();
...
...
Titanium.Web.Proxy/Decompression/DefaultDecompression.cs
View file @
4b86cde8
namespace
Titanium.Web.Proxy.Decompression
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Decompression
{
class
DefaultDecompression
:
IDecompression
{
public
byte
[]
Decompress
(
byte
[]
compressedArray
)
public
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
{
return
compressedArray
;
return
Task
.
FromResult
(
compressedArray
)
;
}
}
}
Titanium.Web.Proxy/Decompression/DeflateDecompression.cs
View file @
4b86cde8
using
Ionic.Zlib
;
using
System.IO
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy.Decompression
{
class
DeflateDecompression
:
IDecompression
{
public
byte
[]
Decompress
(
byte
[]
compressedArray
)
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
{
var
stream
=
new
MemoryStream
(
compressedArray
);
...
...
@@ -17,9 +18,9 @@ namespace Titanium.Web.Proxy.Decompression
using
(
var
output
=
new
MemoryStream
())
{
int
read
;
while
((
read
=
decompressor
.
Read
(
buffer
,
0
,
buffer
.
Length
))
>
0
)
while
((
read
=
await
decompressor
.
ReadAsync
(
buffer
,
0
,
buffer
.
Length
).
ConfigureAwait
(
false
))
>
0
)
{
output
.
Write
(
buffer
,
0
,
read
);
await
output
.
WriteAsync
(
buffer
,
0
,
read
).
ConfigureAwait
(
false
);
}
return
output
.
ToArray
();
...
...
Titanium.Web.Proxy/Decompression/GZipDecompression.cs
View file @
4b86cde8
using
System.IO
;
using
System.IO.Compression
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy.Decompression
{
class
GZipDecompression
:
IDecompression
{
public
byte
[]
Decompress
(
byte
[]
compressedArray
)
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
{
using
(
var
decompressor
=
new
GZipStream
(
new
MemoryStream
(
compressedArray
),
CompressionMode
.
Decompress
))
{
...
...
@@ -14,9 +15,9 @@ namespace Titanium.Web.Proxy.Decompression
using
(
var
output
=
new
MemoryStream
())
{
int
read
;
while
((
read
=
decompressor
.
Read
(
buffer
,
0
,
buffer
.
Length
))
>
0
)
while
((
read
=
await
decompressor
.
ReadAsync
(
buffer
,
0
,
buffer
.
Length
).
ConfigureAwait
(
false
))
>
0
)
{
output
.
Write
(
buffer
,
0
,
read
);
await
output
.
WriteAsync
(
buffer
,
0
,
read
).
ConfigureAwait
(
false
);
}
return
output
.
ToArray
();
}
...
...
Titanium.Web.Proxy/Decompression/IDecompression.cs
View file @
4b86cde8
using
System.IO
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Decompression
{
interface
IDecompression
{
byte
[]
Decompress
(
byte
[]
compressedArray
);
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
);
}
}
Titanium.Web.Proxy/Decompression/ZlibDecompression.cs
View file @
4b86cde8
using
Ionic.Zlib
;
using
System.IO
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy.Decompression
{
class
ZlibDecompression
:
IDecompression
{
public
byte
[]
Decompress
(
byte
[]
compressedArray
)
public
async
Task
<
byte
[
]>
Decompress
(
byte
[]
compressedArray
)
{
var
memoryStream
=
new
MemoryStream
(
compressedArray
);
using
(
var
decompressor
=
new
ZlibStream
(
memoryStream
,
CompressionMode
.
Decompress
))
...
...
@@ -16,9 +17,9 @@ namespace Titanium.Web.Proxy.Decompression
using
(
var
output
=
new
MemoryStream
())
{
int
read
;
while
((
read
=
decompressor
.
Read
(
buffer
,
0
,
buffer
.
Length
))
>
0
)
while
((
read
=
await
decompressor
.
ReadAsync
(
buffer
,
0
,
buffer
.
Length
).
ConfigureAwait
(
false
))
>
0
)
{
output
.
Write
(
buffer
,
0
,
read
);
await
output
.
WriteAsync
(
buffer
,
0
,
read
).
ConfigureAwait
(
false
);
}
return
output
.
ToArray
();
}
...
...
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
4b86cde8
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
View file @
4b86cde8
...
...
@@ -15,12 +15,12 @@ namespace Titanium.Web.Proxy.Extensions
if
(!
string
.
IsNullOrEmpty
(
initialData
))
{
var
bytes
=
Encoding
.
ASCII
.
GetBytes
(
initialData
);
output
.
Write
(
bytes
,
0
,
bytes
.
Length
);
await
output
.
WriteAsync
(
bytes
,
0
,
bytes
.
Length
);
}
await
input
.
CopyToAsync
(
output
);
}
internal
static
void
CopyBytesToStream
(
this
CustomBinaryReader
clientStreamReader
,
Stream
stream
,
long
totalBytesToRead
)
internal
static
async
Task
CopyBytesToStream
(
this
CustomBinaryReader
clientStreamReader
,
Stream
stream
,
long
totalBytesToRead
)
{
var
totalbytesRead
=
0
;
...
...
@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy.Extensions
while
(
totalbytesRead
<
(
int
)
totalBytesToRead
)
{
var
buffer
=
clientStreamReader
.
ReadBytes
(
bytesToRead
);
var
buffer
=
await
clientStreamReader
.
ReadBytesAsync
(
bytesToRead
);
totalbytesRead
+=
buffer
.
Length
;
var
remainingBytes
=
(
int
)
totalBytesToRead
-
totalbytesRead
;
...
...
@@ -43,26 +43,26 @@ namespace Titanium.Web.Proxy.Extensions
{
bytesToRead
=
remainingBytes
;
}
stream
.
Write
(
buffer
,
0
,
buffer
.
Length
);
await
stream
.
WriteAsync
(
buffer
,
0
,
buffer
.
Length
);
}
}
internal
static
void
CopyBytesToStreamChunked
(
this
CustomBinaryReader
clientStreamReader
,
Stream
stream
)
internal
static
async
Task
CopyBytesToStreamChunked
(
this
CustomBinaryReader
clientStreamReader
,
Stream
stream
)
{
while
(
true
)
{
var
chuchkHead
=
clientStreamReader
.
ReadLine
();
var
chuchkHead
=
await
clientStreamReader
.
ReadLineAsync
();
var
chunkSize
=
int
.
Parse
(
chuchkHead
,
NumberStyles
.
HexNumber
);
if
(
chunkSize
!=
0
)
{
var
buffer
=
clientStreamReader
.
ReadBytes
(
chunkSize
);
stream
.
Write
(
buffer
,
0
,
buffer
.
Length
);
var
buffer
=
await
clientStreamReader
.
ReadBytesAsync
(
chunkSize
);
await
stream
.
WriteAsync
(
buffer
,
0
,
buffer
.
Length
);
//chunk trail
clientStreamReader
.
ReadLine
();
await
clientStreamReader
.
ReadLineAsync
();
}
else
{
clientStreamReader
.
ReadLine
();
await
clientStreamReader
.
ReadLineAsync
();
break
;
}
}
...
...
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
View file @
4b86cde8
...
...
@@ -4,6 +4,7 @@ using System.IO;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Shared
;
...
...
@@ -31,7 +32,7 @@ namespace Titanium.Web.Proxy.Helpers
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
internal
string
ReadLine
()
internal
async
Task
<
string
>
ReadLineAsync
()
{
var
readBuffer
=
new
StringBuilder
();
...
...
@@ -40,7 +41,7 @@ namespace Titanium.Web.Proxy.Helpers
var
lastChar
=
default
(
char
);
var
buffer
=
new
byte
[
1
];
while
(
this
.
stream
.
Read
(
buffer
,
0
,
1
)
>
0
)
while
(
await
this
.
stream
.
ReadAsync
(
buffer
,
0
,
1
).
ConfigureAwait
(
false
)
>
0
)
{
if
(
lastChar
==
'\r'
&&
buffer
[
0
]
==
'\n'
)
{
...
...
@@ -66,18 +67,18 @@ namespace Titanium.Web.Proxy.Helpers
/// Read until the last new line
/// </summary>
/// <returns></returns>
internal
List
<
string
>
ReadAllLines
()
internal
async
Task
<
List
<
string
>>
ReadAllLinesAsync
()
{
string
tmpLine
;
var
requestLines
=
new
List
<
string
>();
while
(!
string
.
IsNullOrEmpty
(
tmpLine
=
ReadLine
(
)))
while
(!
string
.
IsNullOrEmpty
(
tmpLine
=
await
ReadLineAsync
().
ConfigureAwait
(
false
)))
{
requestLines
.
Add
(
tmpLine
);
}
return
requestLines
;
}
internal
byte
[]
ReadBytes
(
long
totalBytesToRead
)
internal
async
Task
<
byte
[
]>
ReadBytesAsync
(
long
totalBytesToRead
)
{
int
bytesToRead
=
Constants
.
BUFFER_SIZE
;
...
...
@@ -91,9 +92,9 @@ namespace Titanium.Web.Proxy.Helpers
using
(
var
outStream
=
new
MemoryStream
())
{
while
((
bytesRead
+=
this
.
stream
.
Read
(
buffer
,
0
,
bytesToRead
))
>
0
)
while
((
bytesRead
+=
await
this
.
stream
.
ReadAsync
(
buffer
,
0
,
bytesToRead
).
ConfigureAwait
(
false
))
>
0
)
{
outStream
.
Write
(
buffer
,
0
,
bytesRead
);
await
outStream
.
WriteAsync
(
buffer
,
0
,
bytesRead
).
ConfigureAwait
(
false
);
totalBytesRead
+=
bytesRead
;
if
(
totalBytesRead
==
totalBytesToRead
)
...
...
Titanium.Web.Proxy/Helpers/Tcp.cs
View file @
4b86cde8
...
...
@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy.Helpers
{
public
class
TcpHelper
{
public
static
void
SendRaw
(
Stream
clientStream
,
string
httpCmd
,
List
<
HttpHeader
>
requestHeaders
,
string
hostName
,
public
async
static
Task
SendRaw
(
Stream
clientStream
,
string
httpCmd
,
List
<
HttpHeader
>
requestHeaders
,
string
hostName
,
int
tunnelPort
,
bool
isHttps
)
{
StringBuilder
sb
=
null
;
...
...
@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Helpers
try
{
sslStream
=
new
SslStream
(
tunnelStream
);
sslStream
.
AuthenticateAsClient
(
hostName
,
null
,
Constants
.
SupportedProtocols
,
false
);
await
sslStream
.
AuthenticateAsClientAsync
(
hostName
,
null
,
Constants
.
SupportedProtocols
,
false
);
tunnelStream
=
sslStream
;
}
catch
...
...
@@ -62,17 +62,17 @@ namespace Titanium.Web.Proxy.Helpers
}
}
var
sendRelay
=
Task
.
Factory
.
StartNew
(()
=>
{
if
(
sb
!=
null
)
clientStream
.
CopyToAsync
(
sb
.
ToString
(),
tunnelStream
).
Wait
(
);
else
clientStream
.
CopyToAsync
(
string
.
Empty
,
tunnelStream
).
Wait
(
);
});
Task
sendRelay
;
if
(
sb
!=
null
)
sendRelay
=
clientStream
.
CopyToAsync
(
sb
.
ToString
(),
tunnelStream
);
else
sendRelay
=
clientStream
.
CopyToAsync
(
string
.
Empty
,
tunnelStream
);
var
receiveRelay
=
Task
.
Factory
.
StartNew
(()
=>
tunnelStream
.
CopyToAsync
(
string
.
Empty
,
clientStream
).
Wait
()
);
var
receiveRelay
=
tunnelStream
.
CopyToAsync
(
string
.
Empty
,
clientStream
);
Task
.
WaitAll
(
sendRelay
,
receiveRelay
);
await
Task
.
WhenAll
(
sendRelay
,
receiveRelay
).
ConfigureAwait
(
false
);
}
catch
{
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
4b86cde8
...
...
@@ -2,6 +2,7 @@ using System;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Shared
;
...
...
@@ -35,7 +36,7 @@ namespace Titanium.Web.Proxy.Http
this
.
Response
=
new
Response
();
}
internal
void
SendRequest
()
internal
async
Task
SendRequest
()
{
Stream
stream
=
ProxyClient
.
Stream
;
...
...
@@ -57,13 +58,13 @@ namespace Titanium.Web.Proxy.Http
string
request
=
requestLines
.
ToString
();
byte
[]
requestBytes
=
Encoding
.
ASCII
.
GetBytes
(
request
);
stream
.
Write
(
requestBytes
,
0
,
requestBytes
.
Length
);
await
stream
.
WriteAsync
(
requestBytes
,
0
,
requestBytes
.
Length
);
stream
.
Flush
();
if
(
ProxyServer
.
Enable100ContinueBehaviour
)
if
(
this
.
Request
.
ExpectContinue
)
{
var
httpResult
=
ProxyClient
.
ServerStreamReader
.
ReadLine
(
).
Split
(
Constants
.
SpaceSplit
,
3
);
var
httpResult
=
(
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
()
).
Split
(
Constants
.
SpaceSplit
,
3
);
var
responseStatusCode
=
httpResult
[
1
].
Trim
();
var
responseStatusDescription
=
httpResult
[
2
].
Trim
();
...
...
@@ -72,27 +73,27 @@ namespace Titanium.Web.Proxy.Http
&&
responseStatusDescription
.
ToLower
().
Equals
(
"continue"
))
{
this
.
Request
.
Is100Continue
=
true
;
ProxyClient
.
ServerStreamReader
.
ReadLine
();
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
();
}
else
if
(
responseStatusCode
.
Equals
(
"417"
)
&&
responseStatusDescription
.
ToLower
().
Equals
(
"expectation failed"
))
{
this
.
Request
.
ExpectationFailed
=
true
;
ProxyClient
.
ServerStreamReader
.
ReadLine
();
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
();
}
}
}
internal
void
ReceiveResponse
()
internal
async
Task
ReceiveResponse
()
{
//return if this is already read
if
(
this
.
Response
.
ResponseStatusCode
!=
null
)
return
;
var
httpResult
=
ProxyClient
.
ServerStreamReader
.
ReadLine
(
).
Split
(
Constants
.
SpaceSplit
,
3
);
var
httpResult
=
(
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
()
).
Split
(
Constants
.
SpaceSplit
,
3
);
if
(
string
.
IsNullOrEmpty
(
httpResult
[
0
]))
{
var
s
=
ProxyClient
.
ServerStreamReader
.
ReadLine
();
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
();
}
this
.
Response
.
HttpVersion
=
httpResult
[
0
].
Trim
();
...
...
@@ -105,8 +106,8 @@ namespace Titanium.Web.Proxy.Http
{
this
.
Response
.
Is100Continue
=
true
;
this
.
Response
.
ResponseStatusCode
=
null
;
ProxyClient
.
ServerStreamReader
.
ReadLine
();
ReceiveResponse
();
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
();
await
ReceiveResponse
();
return
;
}
else
if
(
this
.
Response
.
ResponseStatusCode
.
Equals
(
"417"
)
...
...
@@ -114,12 +115,12 @@ namespace Titanium.Web.Proxy.Http
{
this
.
Response
.
ExpectationFailed
=
true
;
this
.
Response
.
ResponseStatusCode
=
null
;
ProxyClient
.
ServerStreamReader
.
ReadLine
();
ReceiveResponse
();
await
ProxyClient
.
ServerStreamReader
.
ReadLineAsync
();
await
ReceiveResponse
();
return
;
}
List
<
string
>
responseLines
=
ProxyClient
.
ServerStreamReader
.
ReadAllLines
();
List
<
string
>
responseLines
=
await
ProxyClient
.
ServerStreamReader
.
ReadAllLinesAsync
();
for
(
int
index
=
0
;
index
<
responseLines
.
Count
;
++
index
)
{
...
...
Titanium.Web.Proxy/Network/TcpConnectionManager.cs
View file @
4b86cde8
...
...
@@ -61,13 +61,15 @@ namespace Titanium.Web.Proxy.Network
}
if
(
cached
==
null
)
cached
=
await
CreateClient
(
sessionArgs
,
hostname
,
port
,
isSecure
,
version
);
cached
=
await
CreateClient
(
sessionArgs
,
hostname
,
port
,
isSecure
,
version
).
ConfigureAwait
(
false
);
//if (ConnectionCache.Where(x => x.HostName == hostname && x.port == port &&
//x.IsSecure == isSecure && x.TcpClient.Connected && x.Version.Equals(version)).Count() < 2)
//{
// Task.Factory.StartNew(() => CreateClient(sessionArgs, hostname, port, isSecure, version));
//}
//just create one more preemptively
if
(
ConnectionCache
.
Where
(
x
=>
x
.
HostName
==
hostname
&&
x
.
port
==
port
&&
x
.
IsSecure
==
isSecure
&&
x
.
TcpClient
.
Connected
&&
x
.
Version
.
Equals
(
version
)).
Count
()
<
2
)
{
var
task
=
CreateClient
(
sessionArgs
,
hostname
,
port
,
isSecure
,
version
)
.
ContinueWith
(
x
=>
ReleaseClient
(
x
.
Result
));
}
return
cached
;
}
...
...
@@ -81,26 +83,26 @@ namespace Titanium.Web.Proxy.Network
{
CustomSslStream
sslStream
=
null
;
if
(
ProxyServer
.
UpStreamHttpsProxy
!=
null
)
if
(
ProxyServer
.
UpStreamHttpsProxy
!=
null
)
{
client
=
new
TcpClient
(
ProxyServer
.
UpStreamHttpsProxy
.
HostName
,
ProxyServer
.
UpStreamHttpsProxy
.
Port
);
stream
=
(
Stream
)
client
.
GetStream
();
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
Constants
.
BUFFER_SIZE
,
true
);
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
Constants
.
BUFFER_SIZE
,
true
);
writer
.
WriteLine
(
string
.
Format
(
"CONNECT {0}:{1} {2}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
,
sessionArgs
.
WebSession
.
Request
.
HttpVersion
));
writer
.
WriteLine
(
string
.
Format
(
"Host: {0}:{1}"
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Host
,
sessionArgs
.
WebSession
.
Request
.
RequestUri
.
Port
));
writer
.
WriteLine
(
"Connection: Keep-Alive"
);
writer
.
WriteLine
();
writer
.
Flush
();
var
reader
=
new
CustomBinaryReader
(
stream
);
var
result
=
reader
.
ReadLine
(
);
var
result
=
await
reader
.
ReadLineAsync
().
ConfigureAwait
(
false
);
if
(!
result
.
ToLower
().
Contains
(
"200 connection established"
))
throw
new
Exception
(
"Upstream proxy failed to create a secure tunnel"
);
reader
.
ReadAllLines
(
);
await
reader
.
ReadAllLinesAsync
().
ConfigureAwait
(
false
);
}
else
{
...
...
@@ -110,9 +112,9 @@ namespace Titanium.Web.Proxy.Network
try
{
sslStream
=
new
CustomSslStream
(
stream
,
true
,
ProxyServer
.
ValidateServerCertificate
);
sslStream
=
new
CustomSslStream
(
stream
,
true
,
new
RemoteCertificateValidationCallback
(
ProxyServer
.
ValidateServerCertificate
)
);
sslStream
.
Session
=
sessionArgs
;
await
sslStream
.
AuthenticateAsClientAsync
(
hostname
,
null
,
Constants
.
SupportedProtocols
,
false
);
await
sslStream
.
AuthenticateAsClientAsync
(
hostname
,
null
,
Constants
.
SupportedProtocols
,
false
)
.
ConfigureAwait
(
false
)
;
stream
=
(
Stream
)
sslStream
;
}
catch
...
...
@@ -155,7 +157,7 @@ namespace Titanium.Web.Proxy.Network
ConnectionCache
.
Add
(
Connection
);
}
internal
static
void
ClearIdleConnections
()
internal
async
static
void
ClearIdleConnections
()
{
while
(
true
)
{
...
...
@@ -171,7 +173,7 @@ namespace Titanium.Web.Proxy.Network
ConnectionCache
.
RemoveAll
(
x
=>
x
.
LastAccess
<
cutOff
);
}
Thread
.
Sleep
(
1000
*
60
*
3
);
await
Task
.
Delay
(
1000
*
60
*
3
).
ConfigureAwait
(
false
);
}
}
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
4b86cde8
...
...
@@ -34,8 +34,8 @@ namespace Titanium.Web.Proxy
public
static
string
RootCertificateName
{
get
;
set
;
}
public
static
bool
Enable100ContinueBehaviour
{
get
;
set
;
}
public
static
event
EventHandler
<
SessionEventArgs
>
BeforeRequest
;
public
static
event
EventHandler
<
SessionEventArgs
>
BeforeResponse
;
public
static
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeRequest
;
public
static
event
Func
<
object
,
SessionEventArgs
,
Task
>
BeforeResponse
;
/// <summary>
/// External proxy for Http
...
...
@@ -50,14 +50,14 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication
/// </summary>
public
static
event
EventHandler
<
CertificateValidationEventArgs
>
Remote
CertificateValidationCallback
;
public
static
event
Func
<
object
,
CertificateValidationEventArgs
,
Task
>
Server
CertificateValidationCallback
;
public
static
List
<
ProxyEndPoint
>
ProxyEndPoints
{
get
;
set
;
}
public
static
void
Initialize
()
{
T
ask
.
Factory
.
StartNew
(()
=>
TcpConnectionManager
.
ClearIdleConnections
()
);
T
cpConnectionManager
.
ClearIdleConnections
(
);
}
public
static
void
AddEndPoint
(
ProxyEndPoint
endPoint
)
...
...
@@ -235,51 +235,6 @@ namespace Titanium.Web.Proxy
}
}
/// <summary>
/// Call back to override server certificate validation
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
internal
static
bool
ValidateServerCertificate
(
object
sender
,
X509Certificate
certificate
,
X509Chain
chain
,
SslPolicyErrors
sslPolicyErrors
)
{
var
param
=
sender
as
CustomSslStream
;
if
(
RemoteCertificateValidationCallback
!=
null
)
{
var
args
=
new
CertificateValidationEventArgs
();
args
.
Session
=
param
.
Session
;
args
.
Certificate
=
certificate
;
args
.
Chain
=
chain
;
args
.
SslPolicyErrors
=
sslPolicyErrors
;
RemoteCertificateValidationCallback
.
Invoke
(
null
,
args
);
if
(!
args
.
IsValid
)
{
param
.
Session
.
WebSession
.
Request
.
CancelRequest
=
true
;
}
return
args
.
IsValid
;
}
if
(
sslPolicyErrors
==
SslPolicyErrors
.
None
)
return
true
;
Console
.
WriteLine
(
"Certificate error: {0}"
,
sslPolicyErrors
);
//By default
//do not allow this client to communicate with unauthenticated servers.
return
false
;
}
}
}
\ No newline at end of file
Titanium.Web.Proxy/RequestHandler.cs
View file @
4b86cde8
This diff is collapsed.
Click to expand it.
Titanium.Web.Proxy/ResponseHandler.cs
View file @
4b86cde8
This diff is collapsed.
Click to expand it.
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