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
9afb81c6
Commit
9afb81c6
authored
May 16, 2017
by
Jehonathan Thomas
Committed by
GitHub
May 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #238 from justcoding121/develop
Beta
parents
69aa70c1
3e58c39d
Show whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
401 additions
and
303 deletions
+401
-303
ConsoleHelper.cs
...itanium.Web.Proxy.Examples.Basic/Helpers/ConsoleHelper.cs
+52
-0
Program.cs
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
+8
-2
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+7
-7
Titanium.Web.Proxy.Examples.Basic.csproj
...y.Examples.Basic/Titanium.Web.Proxy.Examples.Basic.csproj
+1
-0
AssemblyInfo.cs
...ium.Web.Proxy.IntegrationTests/Properties/AssemblyInfo.cs
+0
-1
SslTests.cs
Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
+5
-5
CertificateManagerTests.cs
...s/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
+3
-7
Titanium.Web.Proxy.sln.DotSettings
Titanium.Web.Proxy.sln.DotSettings
+14
-1
CertificateHandler.cs
Titanium.Web.Proxy/CertificateHandler.cs
+5
-23
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+8
-7
FuncExtensions.cs
Titanium.Web.Proxy/Extensions/FuncExtensions.cs
+34
-0
StreamExtensions.cs
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
+3
-3
CustomBinaryReader.cs
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
+22
-3
CustomBufferedStream.cs
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
+1
-1
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+4
-4
Tcp.cs
Titanium.Web.Proxy/Helpers/Tcp.cs
+2
-5
HeaderParser.cs
Titanium.Web.Proxy/Http/HeaderParser.cs
+2
-2
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+18
-3
Request.cs
Titanium.Web.Proxy/Http/Request.cs
+2
-2
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+3
-3
GenericResponse.cs
Titanium.Web.Proxy/Http/Responses/GenericResponse.cs
+1
-1
BCCertificateMaker.cs
Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs
+1
-1
WinCertificateMaker.cs
...nium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
+20
-21
CertificateManager.cs
Titanium.Web.Proxy/Network/CertificateManager.cs
+9
-8
TcpConnection.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
+15
-1
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+13
-15
ProxyAuthorizationHandler.cs
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
+2
-2
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+29
-19
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+95
-128
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+18
-25
ProxyConstants.cs
Titanium.Web.Proxy/Shared/ProxyConstants.cs
+3
-3
Titanium.Web.Proxy.csproj
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+1
-0
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/Helpers/ConsoleHelper.cs
0 → 100644
View file @
9afb81c6
using
System
;
using
System.Runtime.InteropServices
;
namespace
Titanium.Web.Proxy.Examples.Basic.Helpers
{
/// <summary>
/// Adapated from
/// http://stackoverflow.com/questions/13656846/how-to-programmatic-disable-c-sharp-console-applications-quick-edit-mode
/// </summary>
internal
static
class
ConsoleHelper
{
const
uint
ENABLE_QUICK_EDIT
=
0x0040
;
// STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
const
int
STD_INPUT_HANDLE
=
-
10
;
[
DllImport
(
"kernel32.dll"
,
SetLastError
=
true
)]
static
extern
IntPtr
GetStdHandle
(
int
nStdHandle
);
[
DllImport
(
"kernel32.dll"
)]
static
extern
bool
GetConsoleMode
(
IntPtr
hConsoleHandle
,
out
uint
lpMode
);
[
DllImport
(
"kernel32.dll"
)]
static
extern
bool
SetConsoleMode
(
IntPtr
hConsoleHandle
,
uint
dwMode
);
internal
static
bool
DisableQuickEditMode
()
{
IntPtr
consoleHandle
=
GetStdHandle
(
STD_INPUT_HANDLE
);
// get current console mode
uint
consoleMode
;
if
(!
GetConsoleMode
(
consoleHandle
,
out
consoleMode
))
{
// ERROR: Unable to get console mode.
return
false
;
}
// Clear the quick edit bit in the mode flags
consoleMode
&=
~
ENABLE_QUICK_EDIT
;
// set the new mode
if
(!
SetConsoleMode
(
consoleHandle
,
consoleMode
))
{
// ERROR: Unable to set console mode
return
false
;
}
return
true
;
}
}
}
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
View file @
9afb81c6
using
System
;
using
System.Diagnostics
;
using
System.Runtime.InteropServices
;
using
Titanium.Web.Proxy.Examples.Basic.Helpers
;
namespace
Titanium.Web.Proxy.Examples.Basic
{
...
...
@@ -9,11 +11,13 @@ namespace Titanium.Web.Proxy.Examples.Basic
public
static
void
Main
(
string
[]
args
)
{
//fix console hang due to QuickEdit mode
ConsoleHelper
.
DisableQuickEditMode
();
//On Console exit make sure we also exit the proxy
NativeMethods
.
Handler
=
ConsoleEventCallback
;
NativeMethods
.
SetConsoleCtrlHandler
(
NativeMethods
.
Handler
,
true
);
//Start proxy controller
controller
.
StartProxy
();
...
...
@@ -50,5 +54,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
// Pinvoke
internal
delegate
bool
ConsoleEventDelegate
(
int
eventType
);
}
}
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Net
;
using
System.Net.Security
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
...
...
@@ -47,18 +47,18 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example google.com and dropbox.com
ExcludedHttpsHostNameRegex
=
new
List
<
string
>()
{
"dropbox.com"
}
ExcludedHttpsHostNameRegex
=
new
List
<
string
>
{
"dropbox.com"
}
//Include Https addresses you want to proxy (others will be excluded)
//for example github.com
//
IncludedHttpsHostNameRegex = new List<string>()
{ "github.com" }
//
IncludedHttpsHostNameRegex = new List<string>
{ "github.com" }
//You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown
//Use self-issued generic certificate on all https requests
//Optimizes performance by not creating a certificate for each https-enabled domain
//Useful when certificate trust is not required by proxy clients
//
GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
//GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
};
//An explicit endpoint is where the client knows about the existence of a proxy
...
...
@@ -107,7 +107,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//intecept & cancel redirect or update requests
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
Console
.
WriteLine
(
"Active Client Connections:"
+
((
ProxyServer
)
sender
).
ClientConnectionCount
);
Console
.
WriteLine
(
"Active Client Connections:"
+
((
ProxyServer
)
sender
).
ClientConnectionCount
);
Console
.
WriteLine
(
e
.
WebSession
.
Request
.
Url
);
//read request headers
...
...
@@ -150,7 +150,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Modify response
public
async
Task
OnResponse
(
object
sender
,
SessionEventArgs
e
)
{
Console
.
WriteLine
(
"Active Server Connections:"
+
(
sender
as
ProxyServ
er
).
ServerConnectionCount
);
Console
.
WriteLine
(
"Active Server Connections:"
+
(
(
ProxyServer
)
send
er
).
ServerConnectionCount
);
if
(
requestBodyHistory
.
ContainsKey
(
e
.
Id
))
{
...
...
@@ -189,7 +189,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
public
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
//set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
S
ystem
.
Net
.
Security
.
S
slPolicyErrors
.
None
)
if
(
e
.
SslPolicyErrors
==
SslPolicyErrors
.
None
)
{
e
.
IsValid
=
true
;
}
...
...
Examples/Titanium.Web.Proxy.Examples.Basic/Titanium.Web.Proxy.Examples.Basic.csproj
View file @
9afb81c6
...
...
@@ -55,6 +55,7 @@
<Reference
Include=
"System.Xml"
/>
</ItemGroup>
<ItemGroup>
<Compile
Include=
"Helpers\ConsoleHelper.cs"
/>
<Compile
Include=
"Program.cs"
/>
<Compile
Include=
"Properties\AssemblyInfo.cs"
/>
<Compile
Include=
"ProxyTestController.cs"
/>
...
...
Tests/Titanium.Web.Proxy.IntegrationTests/Properties/AssemblyInfo.cs
View file @
9afb81c6
using
System.Reflection
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
// General Information about an assembly is controlled through the following
...
...
Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
View file @
9afb81c6
using
System
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
System.Diagnostics
;
using
System.Net
;
using
System.Net.Http
;
using
System.Net.Security
;
using
System.Threading.Tasks
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
using
System.Net.Http
;
using
System.Diagnostics
;
namespace
Titanium.Web.Proxy.IntegrationTests
{
...
...
@@ -13,7 +14,6 @@ namespace Titanium.Web.Proxy.IntegrationTests
public
class
SslTests
{
[
TestMethod
]
public
void
TestSsl
()
{
//expand this to stress test to find
...
...
@@ -103,7 +103,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
public
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
//set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
S
ystem
.
Net
.
Security
.
S
slPolicyErrors
.
None
)
if
(
e
.
SslPolicyErrors
==
SslPolicyErrors
.
None
)
{
e
.
IsValid
=
true
;
}
...
...
Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Generic
;
using
System.Threading.Tasks
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
Titanium.Web.Proxy.Network
;
using
System.Threading.Tasks
;
using
System.Collections.Generic
;
namespace
Titanium.Web.Proxy.UnitTests
{
...
...
@@ -10,8 +10,7 @@ namespace Titanium.Web.Proxy.UnitTests
public
class
CertificateManagerTests
{
private
static
readonly
string
[]
hostNames
=
new
string
[]
{
"facebook.com"
,
"youtube.com"
,
"google.com"
,
"bing.com"
,
"yahoo.com"
};
=
{
"facebook.com"
,
"youtube.com"
,
"google.com"
,
"bing.com"
,
"yahoo.com"
};
private
readonly
Random
random
=
new
Random
();
...
...
@@ -36,16 +35,13 @@ namespace Titanium.Web.Proxy.UnitTests
var
certificate
=
mgr
.
CreateCertificate
(
host
,
false
);
Assert
.
IsNotNull
(
certificate
);
}));
}
}
await
Task
.
WhenAll
(
tasks
.
ToArray
());
mgr
.
StopClearIdleCertificates
();
}
}
}
Titanium.Web.Proxy.sln.DotSettings
View file @
9afb81c6
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">240</s:Int64>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BC/@EntryIndexedValue">BC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CN/@EntryIndexedValue">CN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DN/@EntryIndexedValue">DN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EKU/@EntryIndexedValue">EKU</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=KU/@EntryIndexedValue">KU</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MTA/@EntryIndexedValue">MTA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OID/@EntryIndexedValue">OID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OIDS/@EntryIndexedValue">OIDS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String></wpf:ResourceDictionary>
\ No newline at end of file
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue"><Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy></s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
\ No newline at end of file
Titanium.Web.Proxy/CertificateHandler.cs
View file @
9afb81c6
using
System
;
using
System.Net.Security
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Extensions
;
namespace
Titanium.Web.Proxy
{
...
...
@@ -32,17 +32,8 @@ namespace Titanium.Web.Proxy
SslPolicyErrors
=
sslPolicyErrors
};
Delegate
[]
invocationList
=
ServerCertificateValidationCallback
.
GetInvocationList
();
Task
[]
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
CertificateValidationEventArgs
,
Task
>)
invocationList
[
i
])(
null
,
args
);
}
Task
.
WhenAll
(
handlerTasks
).
Wait
();
//why is the sender null?
ServerCertificateValidationCallback
.
InvokeParallel
(
this
,
args
);
return
args
.
IsValid
;
}
...
...
@@ -108,17 +99,8 @@ namespace Titanium.Web.Proxy
ClientCertificate
=
clientCertificate
};
Delegate
[]
invocationList
=
ClientCertificateSelectionCallback
.
GetInvocationList
();
Task
[]
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
CertificateSelectionEventArgs
,
Task
>)
invocationList
[
i
])(
null
,
args
);
}
Task
.
WhenAll
(
handlerTasks
).
Wait
();
//why is the sender null?
ClientCertificateSelectionCallback
.
InvokeParallel
(
this
,
args
);
return
args
.
ClientCertificate
;
}
...
...
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Net
;
using
System.Text
;
using
Titanium.Web.Proxy.Exception
s
;
using
System.Threading.Task
s
;
using
Titanium.Web.Proxy.Decompression
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Http.Responses
;
using
Titanium.Web.Proxy.Extensions
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Network
;
using
System.Net
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
namespace
Titanium.Web.Proxy.EventArguments
{
...
...
@@ -56,7 +56,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// Client End Point.
/// </summary>
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
TcpClient
.
Client
.
RemoteEndPoint
;
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
TcpClient
.
Client
.
RemoteEndPoint
;
/// <summary>
/// A web session corresponding to a single request/response sequence
...
...
@@ -158,7 +158,7 @@ namespace Titanium.Web.Proxy.EventArguments
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
}
else
if
(
(
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
||
WebSession
.
Response
.
ContentLength
==
-
1
)
else
if
(
WebSession
.
Response
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
||
WebSession
.
Response
.
ContentLength
==
-
1
)
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
bufferSize
,
responseBodyStream
,
long
.
MaxValue
);
}
...
...
@@ -522,6 +522,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
void
Dispose
()
{
WebSession
.
Dispose
();
}
}
}
Titanium.Web.Proxy/Extensions/FuncExtensions.cs
0 → 100644
View file @
9afb81c6
using
System
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Extensions
{
internal
static
class
FuncExtensions
{
public
static
void
InvokeParallel
<
T
>(
this
Func
<
object
,
T
,
Task
>
callback
,
object
sender
,
T
args
)
{
Delegate
[]
invocationList
=
callback
.
GetInvocationList
();
Task
[]
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
T
,
Task
>)
invocationList
[
i
])(
sender
,
args
);
}
Task
.
WhenAll
(
handlerTasks
).
Wait
();
}
public
static
async
Task
InvokeParallelAsync
<
T
>(
this
Func
<
object
,
T
,
Task
>
callback
,
object
sender
,
T
args
)
{
Delegate
[]
invocationList
=
callback
.
GetInvocationList
();
Task
[]
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
T
,
Task
>)
invocationList
[
i
])(
sender
,
args
);
}
await
Task
.
WhenAll
(
handlerTasks
);
}
}
}
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
View file @
9afb81c6
...
...
@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Extensions
if
(
contentLength
<
bufferSize
)
{
bytesToRead
=
(
int
)
contentLength
;
bytesToRead
=
(
int
)
contentLength
;
}
var
buffer
=
new
byte
[
bufferSize
];
...
...
@@ -153,8 +153,8 @@ namespace Titanium.Web.Proxy.Extensions
break
;
bytesRead
=
0
;
var
remainingBytes
=
(
contentLength
-
totalBytesRead
)
;
bytesToRead
=
remainingBytes
>
(
long
)
bufferSize
?
bufferSize
:
(
int
)
remainingBytes
;
var
remainingBytes
=
contentLength
-
totalBytesRead
;
bytesToRead
=
remainingBytes
>
(
long
)
bufferSize
?
bufferSize
:
(
int
)
remainingBytes
;
}
}
else
...
...
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Text
;
...
...
@@ -18,10 +19,18 @@ namespace Titanium.Web.Proxy.Helpers
private
readonly
byte
[]
staticBuffer
;
private
readonly
Encoding
encoding
;
private
static
readonly
ConcurrentQueue
<
byte
[
]>
buffers
=
new
ConcurrentQueue
<
byte
[
]>
();
private
volatile
bool
disposed
;
internal
CustomBinaryReader
(
CustomBufferedStream
stream
,
int
bufferSize
)
{
this
.
stream
=
stream
;
if
(!
buffers
.
TryDequeue
(
out
staticBuffer
)
||
staticBuffer
.
Length
!=
bufferSize
)
{
staticBuffer
=
new
byte
[
bufferSize
];
}
this
.
bufferSize
=
bufferSize
;
...
...
@@ -112,7 +121,7 @@ namespace Titanium.Web.Proxy.Helpers
var
buffer
=
staticBuffer
;
if
(
totalBytesToRead
<
bufferSize
)
{
bytesToRead
=
(
int
)
totalBytesToRead
;
bytesToRead
=
(
int
)
totalBytesToRead
;
buffer
=
new
byte
[
bytesToRead
];
}
...
...
@@ -127,7 +136,7 @@ namespace Titanium.Web.Proxy.Helpers
break
;
var
remainingBytes
=
totalBytesToRead
-
totalBytesRead
;
bytesToRead
=
Math
.
Min
(
bufferSize
,
(
int
)
remainingBytes
);
bytesToRead
=
Math
.
Min
(
bufferSize
,
(
int
)
remainingBytes
);
if
(
totalBytesRead
+
bytesToRead
>
buffer
.
Length
)
{
...
...
@@ -148,8 +157,18 @@ namespace Titanium.Web.Proxy.Helpers
public
void
Dispose
()
{
if
(!
disposed
)
{
disposed
=
true
;
buffers
.
Enqueue
(
staticBuffer
);
}
}
/// <summary>
/// Increase size of buffer and copy existing content to new buffer
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
private
void
ResizeBuffer
(
ref
byte
[]
buffer
,
long
size
)
{
var
newBuffer
=
new
byte
[
size
];
...
...
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
View file @
9afb81c6
...
...
@@ -198,7 +198,7 @@ namespace Titanium.Web.Proxy.Helpers
{
if
(
asyncResult
is
ReadAsyncResult
)
{
return
((
ReadAsyncResult
)
asyncResult
).
ReadBytes
;
return
((
ReadAsyncResult
)
asyncResult
).
ReadBytes
;
}
return
baseStream
.
EndRead
(
asyncResult
);
...
...
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
9afb81c6
using
System
;
using
System.Runtime.InteropServices
;
using
Microsoft.Win32
;
using
System.Text.RegularExpressions
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Runtime.InteropServices
;
using
System.Text.RegularExpressions
;
using
Microsoft.Win32
;
// Helper classes for setting system proxy settings
namespace
Titanium.Web.Proxy.Helpers
...
...
@@ -84,7 +84,7 @@ namespace Titanium.Web.Proxy.Helpers
var
exisitingContent
=
reg
.
GetValue
(
"ProxyServer"
)
as
string
;
var
existingSystemProxyValues
=
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
protocolType
==
ProxyProtocolType
.
Https
?
x
.
IsHttps
:
!
x
.
IsHttps
);
existingSystemProxyValues
.
Add
(
new
HttpSystemProxyValue
()
existingSystemProxyValues
.
Add
(
new
HttpSystemProxyValue
{
HostName
=
hostname
,
IsHttps
=
protocolType
==
ProxyProtocolType
.
Https
,
...
...
Titanium.Web.Proxy/Helpers/Tcp.cs
View file @
9afb81c6
...
...
@@ -3,10 +3,9 @@ using System.Collections.Generic;
using
System.IO
;
using
System.Linq
;
using
System.Net.NetworkInformation
;
using
System.Net.Security
;
using
System.Runtime.InteropServices
;
using
System.Security.Authentication
;
using
System.Text
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Models
;
...
...
@@ -15,8 +14,6 @@ using Titanium.Web.Proxy.Shared;
namespace
Titanium.Web.Proxy.Helpers
{
using
System.Net
;
internal
enum
IpVersion
{
Ipv4
=
1
,
...
...
@@ -232,7 +229,7 @@ namespace Titanium.Web.Proxy.Helpers
finally
{
tcpConnection
.
Dispose
();
server
.
ServerConnectionCount
--
;
Interlocked
.
Decrement
(
ref
server
.
ServerConnectionCountField
)
;
}
}
}
...
...
Titanium.Web.Proxy/Http/HeaderParser.cs
View file @
9afb81c6
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
9afb81c6
...
...
@@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Used to communicate with the server over HTTP(S)
/// </summary>
public
class
HttpWebClient
public
class
HttpWebClient
:
IDisposable
{
/// <summary>
/// Connection to server
...
...
@@ -79,7 +79,7 @@ namespace Titanium.Web.Proxy.Http
var
requestLines
=
new
StringBuilder
();
//prepare the request & headers
if
(
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
)
||
(
ServerConnection
.
UpStreamHttpsProxy
!=
null
&&
ServerConnection
.
IsHttps
)
)
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
||
ServerConnection
.
UpStreamHttpsProxy
!=
null
&&
ServerConnection
.
IsHttps
)
{
requestLines
.
AppendLine
(
$"
{
Request
.
Method
}
{
Request
.
RequestUri
.
AbsoluteUri
}
HTTP/
{
Request
.
HttpVersion
.
Major
}
.
{
Request
.
HttpVersion
.
Minor
}
"
);
}
...
...
@@ -208,5 +208,20 @@ namespace Titanium.Web.Proxy.Http
//Read the response headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
ServerConnection
.
StreamReader
,
Response
.
NonUniqueResponseHeaders
,
Response
.
ResponseHeaders
);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public
void
Dispose
()
{
//not really needed since GC will collect it
//but just to be on safe side
Request
.
RequestBody
=
null
;
Response
.
ResponseBody
=
null
;
Request
.
RequestBodyString
=
null
;
Response
.
ResponseBodyString
=
null
;
}
}
}
Titanium.Web.Proxy/Http/Request.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Generic
;
using
System.Text
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.Http
{
...
...
Titanium.Web.Proxy/Http/Response.cs
View file @
9afb81c6
using
System.Collections.Generic
;
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Text
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Extensions
;
using
System
;
using
Titanium.Web.Proxy.Models
;
namespace
Titanium.Web.Proxy.Http
{
...
...
Titanium.Web.Proxy/Http/Responses/GenericResponse.cs
View file @
9afb81c6
...
...
@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Http.Responses
/// <param name="status"></param>
public
GenericResponse
(
HttpStatusCode
status
)
{
ResponseStatusCode
=
((
int
)
status
).
ToString
();
ResponseStatusCode
=
((
int
)
status
).
ToString
();
ResponseStatusDescription
=
status
.
ToString
();
}
...
...
Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs
View file @
9afb81c6
...
...
@@ -110,7 +110,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
// Corresponding private key
var
privateKeyInfo
=
PrivateKeyInfoFactory
.
CreatePrivateKeyInfo
(
subjectKeyPair
.
Private
);
var
seq
=
(
Asn1Sequence
)
Asn1Object
.
FromByteArray
(
privateKeyInfo
.
ParsePrivateKey
().
GetDerEncoded
());
var
seq
=
(
Asn1Sequence
)
Asn1Object
.
FromByteArray
(
privateKeyInfo
.
ParsePrivateKey
().
GetDerEncoded
());
if
(
seq
.
Count
!=
9
)
{
...
...
Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
View file @
9afb81c6
...
...
@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
}
var
x500CertDN
=
Activator
.
CreateInstance
(
typeX500DN
);
var
typeValue
=
new
object
[]
{
fullSubject
,
0
};
var
typeValue
=
new
object
[]
{
fullSubject
,
0
};
typeX500DN
.
InvokeMember
(
"Encode"
,
BindingFlags
.
InvokeMethod
,
null
,
x500CertDN
,
typeValue
);
var
x500RootCertDN
=
Activator
.
CreateInstance
(
typeX500DN
);
...
...
@@ -110,16 +110,16 @@ namespace Titanium.Web.Proxy.Network.Certificate
if
(
sharedPrivateKey
==
null
)
{
sharedPrivateKey
=
Activator
.
CreateInstance
(
typeX509PrivateKey
);
typeValue
=
new
object
[]
{
sProviderName
};
typeValue
=
new
object
[]
{
sProviderName
};
typeX509PrivateKey
.
InvokeMember
(
"ProviderName"
,
BindingFlags
.
PutDispProperty
,
null
,
sharedPrivateKey
,
typeValue
);
typeValue
[
0
]
=
2
;
typeX509PrivateKey
.
InvokeMember
(
"ExportPolicy"
,
BindingFlags
.
PutDispProperty
,
null
,
sharedPrivateKey
,
typeValue
);
typeValue
=
new
object
[]
{
(
isRoot
?
2
:
1
)
};
typeValue
=
new
object
[]
{
isRoot
?
2
:
1
};
typeX509PrivateKey
.
InvokeMember
(
"KeySpec"
,
BindingFlags
.
PutDispProperty
,
null
,
sharedPrivateKey
,
typeValue
);
if
(!
isRoot
)
{
typeValue
=
new
object
[]
{
176
};
typeValue
=
new
object
[]
{
176
};
typeX509PrivateKey
.
InvokeMember
(
"KeyUsage"
,
BindingFlags
.
PutDispProperty
,
null
,
sharedPrivateKey
,
typeValue
);
}
...
...
@@ -149,9 +149,9 @@ namespace Titanium.Web.Proxy.Network.Certificate
var
requestCert
=
Activator
.
CreateInstance
(
typeRequestCert
);
typeValue
=
new
[]
{
1
,
sharedPrivateKey
,
string
.
Empty
};
typeValue
=
new
[]
{
1
,
sharedPrivateKey
,
string
.
Empty
};
typeRequestCert
.
InvokeMember
(
"InitializeFromPrivateKey"
,
BindingFlags
.
InvokeMethod
,
null
,
requestCert
,
typeValue
);
typeValue
=
new
[]
{
x500CertDN
};
typeValue
=
new
[]
{
x500CertDN
};
typeRequestCert
.
InvokeMember
(
"Subject"
,
BindingFlags
.
PutDispProperty
,
null
,
requestCert
,
typeValue
);
typeValue
[
0
]
=
x500RootCertDN
;
typeRequestCert
.
InvokeMember
(
"Issuer"
,
BindingFlags
.
PutDispProperty
,
null
,
requestCert
,
typeValue
);
...
...
@@ -186,14 +186,14 @@ namespace Titanium.Web.Proxy.Network.Certificate
var
extNames
=
Activator
.
CreateInstance
(
typeExtNames
);
var
altDnsNames
=
Activator
.
CreateInstance
(
typeCAlternativeName
);
typeValue
=
new
object
[]
{
3
,
subject
};
typeValue
=
new
object
[]
{
3
,
subject
};
typeCAlternativeName
.
InvokeMember
(
"InitializeFromString"
,
BindingFlags
.
InvokeMethod
,
null
,
altDnsNames
,
typeValue
);
typeValue
=
new
[]
{
altDnsNames
};
typeValue
=
new
[]
{
altDnsNames
};
typeAltNamesCollection
.
InvokeMember
(
"Add"
,
BindingFlags
.
InvokeMethod
,
null
,
altNameCollection
,
typeValue
);
typeValue
=
new
[]
{
altNameCollection
};
typeValue
=
new
[]
{
altNameCollection
};
typeExtNames
.
InvokeMember
(
"InitializeEncode"
,
BindingFlags
.
InvokeMethod
,
null
,
extNames
,
typeValue
);
typeValue
[
0
]
=
extNames
;
...
...
@@ -204,27 +204,27 @@ namespace Titanium.Web.Proxy.Network.Certificate
{
var
signerCertificate
=
Activator
.
CreateInstance
(
typeSignerCertificate
);
typeValue
=
new
object
[]
{
0
,
0
,
12
,
signingCertificate
.
Thumbprint
};
typeValue
=
new
object
[]
{
0
,
0
,
12
,
signingCertificate
.
Thumbprint
};
typeSignerCertificate
.
InvokeMember
(
"Initialize"
,
BindingFlags
.
InvokeMethod
,
null
,
signerCertificate
,
typeValue
);
typeValue
=
new
[]
{
signerCertificate
};
typeValue
=
new
[]
{
signerCertificate
};
typeRequestCert
.
InvokeMember
(
"SignerCertificate"
,
BindingFlags
.
PutDispProperty
,
null
,
requestCert
,
typeValue
);
}
else
{
var
basicConstraints
=
Activator
.
CreateInstance
(
typeBasicConstraints
);
typeValue
=
new
object
[]
{
"true"
,
"0"
};
typeValue
=
new
object
[]
{
"true"
,
"0"
};
typeBasicConstraints
.
InvokeMember
(
"InitializeEncode"
,
BindingFlags
.
InvokeMethod
,
null
,
basicConstraints
,
typeValue
);
typeValue
=
new
[]
{
basicConstraints
};
typeValue
=
new
[]
{
basicConstraints
};
typeX509Extensions
.
InvokeMember
(
"Add"
,
BindingFlags
.
InvokeMethod
,
null
,
certificate
,
typeValue
);
}
oid
=
Activator
.
CreateInstance
(
typeOID
);
typeValue
=
new
object
[]
{
1
,
0
,
0
,
hashAlg
};
typeValue
=
new
object
[]
{
1
,
0
,
0
,
hashAlg
};
typeOID
.
InvokeMember
(
"InitializeFromAlgorithmName"
,
BindingFlags
.
InvokeMethod
,
null
,
oid
,
typeValue
);
typeValue
=
new
[]
{
oid
};
typeValue
=
new
[]
{
oid
};
typeRequestCert
.
InvokeMember
(
"HashAlgorithm"
,
BindingFlags
.
PutDispProperty
,
null
,
requestCert
,
typeValue
);
typeRequestCert
.
InvokeMember
(
"Encode"
,
BindingFlags
.
InvokeMethod
,
null
,
requestCert
,
null
);
...
...
@@ -244,14 +244,14 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeValue
[
0
]
=
0
;
var
createCertRequest
=
typeX509Enrollment
.
InvokeMember
(
"CreateRequest"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
typeValue
=
new
[]
{
2
,
createCertRequest
,
0
,
string
.
Empty
};
typeValue
=
new
[]
{
2
,
createCertRequest
,
0
,
string
.
Empty
};
typeX509Enrollment
.
InvokeMember
(
"InstallResponse"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
typeValue
=
new
object
[]
{
null
,
0
,
1
};
typeValue
=
new
object
[]
{
null
,
0
,
1
};
try
{
var
empty
=
(
string
)
typeX509Enrollment
.
InvokeMember
(
"CreatePFX"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
var
empty
=
(
string
)
typeX509Enrollment
.
InvokeMember
(
"CreatePFX"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
return
new
X509Certificate2
(
Convert
.
FromBase64String
(
empty
),
string
.
Empty
,
X509KeyStorageFlags
.
Exportable
);
}
catch
(
Exception
)
...
...
@@ -293,8 +293,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
var
graceTime
=
DateTime
.
Now
.
AddDays
(
GraceDays
);
var
now
=
DateTime
.
Now
;
rCert
=
!
isRoot
?
MakeCertificate
(
false
,
sSubjectCN
,
fullSubject
,
keyLength
,
HashAlgo
,
graceTime
,
now
.
AddDays
(
ValidDays
),
signingCert
)
:
MakeCertificate
(
true
,
sSubjectCN
,
fullSubject
,
keyLength
,
HashAlgo
,
graceTime
,
now
.
AddDays
(
ValidDays
),
null
);
rCert
=
MakeCertificate
(
isRoot
,
sSubjectCN
,
fullSubject
,
keyLength
,
HashAlgo
,
graceTime
,
now
.
AddDays
(
ValidDays
),
isRoot
?
null
:
signingCert
);
return
rCert
;
}
}
...
...
Titanium.Web.Proxy/Network/CertificateManager.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Linq
;
using
System.Reflection
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Threading.Tasks
;
using
System.Linq
;
using
System.Collections.Concurrent
;
using
System.IO
;
using
Titanium.Web.Proxy.Network.Certificate
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Network.Certificate
;
namespace
Titanium.Web.Proxy.Network
{
...
...
@@ -51,7 +52,7 @@ namespace Titanium.Web.Proxy.Network
if
(
certEngine
==
null
)
{
certEngine
=
engine
==
CertificateEngine
.
BouncyCastle
?
(
ICertificateMaker
)
new
BCCertificateMaker
()
?
(
ICertificateMaker
)
new
BCCertificateMaker
()
:
new
WinCertificateMaker
();
}
}
...
...
@@ -132,12 +133,12 @@ namespace Titanium.Web.Proxy.Network
private
string
GetRootCertificatePath
()
{
var
assemblyLocation
=
System
.
Reflection
.
Assembly
.
GetExecutingAssembly
().
Location
;
var
assemblyLocation
=
Assembly
.
GetExecutingAssembly
().
Location
;
// dynamically loaded assemblies returns string.Empty location
if
(
assemblyLocation
==
string
.
Empty
)
{
assemblyLocation
=
System
.
Reflection
.
Assembly
.
GetEntryAssembly
().
Location
;
assemblyLocation
=
Assembly
.
GetEntryAssembly
().
Location
;
}
var
path
=
Path
.
GetDirectoryName
(
assemblyLocation
);
...
...
@@ -264,7 +265,7 @@ namespace Titanium.Web.Proxy.Network
}
if
(
certificate
!=
null
&&
!
certificateCache
.
ContainsKey
(
certificateName
))
{
certificateCache
.
Add
(
certificateName
,
new
CachedCertificate
{
Certificate
=
certificate
});
certificateCache
.
Add
(
certificateName
,
new
CachedCertificate
{
Certificate
=
certificate
});
}
}
else
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnection.cs
View file @
9afb81c6
...
...
@@ -58,7 +58,21 @@ namespace Titanium.Web.Proxy.Network.Tcp
StreamReader
?.
Dispose
();
TcpClient
?.
Close
();
try
{
if
(
TcpClient
!=
null
)
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
TcpClient
.
LingerState
=
new
LingerOption
(
true
,
0
);
TcpClient
.
Close
();
}
}
catch
{
}
}
}
}
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
9afb81c6
using
System
;
using
System.IO
;
using
System.Linq
;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Text
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
System.IO
;
using
System.Net.Security
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
using
System.Linq
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy.Network.Tcp
...
...
@@ -17,7 +18,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
internal
class
TcpConnectionFactory
{
/// <summary>
/// Creates a TCP connection to server
/// </summary>
...
...
@@ -39,10 +39,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
TcpClient
client
;
CustomBufferedStream
stream
;
bool
isLocalhost
=
(
externalHttpsProxy
==
null
&&
externalHttpProxy
==
null
)
?
false
:
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
);
bool
isLocalhost
=
(
externalHttpsProxy
!=
null
||
externalHttpProxy
!=
null
)
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
);
bool
useHttpsProxy
=
externalHttpsProxy
!=
null
&&
externalHttpsProxy
.
HostName
!=
remoteHostName
&&
(
externalHttpsProxy
.
BypassForLocalhost
&&
!
isLocalhost
)
;
bool
useHttpProxy
=
externalHttpProxy
!=
null
&&
externalHttpProxy
.
HostName
!=
remoteHostName
&&
(
externalHttpProxy
.
BypassForLocalhost
&&
!
isLocalhost
)
;
bool
useHttpsProxy
=
externalHttpsProxy
!=
null
&&
externalHttpsProxy
.
HostName
!=
remoteHostName
&&
externalHttpsProxy
.
BypassForLocalhost
&&
!
isLocalhost
;
bool
useHttpProxy
=
externalHttpProxy
!=
null
&&
externalHttpProxy
.
HostName
!=
remoteHostName
&&
externalHttpProxy
.
BypassForLocalhost
&&
!
isLocalhost
;
if
(
isHttps
)
{
...
...
@@ -55,7 +55,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
await
client
.
ConnectAsync
(
externalHttpsProxy
.
HostName
,
externalHttpsProxy
.
Port
);
stream
=
new
CustomBufferedStream
(
client
.
GetStream
(),
server
.
BufferSize
);
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
server
.
BufferSize
,
true
)
{
NewLine
=
ProxyConstants
.
NewLine
})
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
server
.
BufferSize
,
true
)
{
NewLine
=
ProxyConstants
.
NewLine
})
{
await
writer
.
WriteLineAsync
(
$"CONNECT
{
remoteHostName
}
:
{
remotePort
}
HTTP/
{
httpVersion
}
"
);
await
writer
.
WriteLineAsync
(
$"Host:
{
remoteHostName
}
:
{
remotePort
}
"
);
...
...
@@ -75,7 +75,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
var
result
=
await
reader
.
ReadLineAsync
();
if
(!
new
[]
{
"200 OK"
,
"connection established"
}.
Any
(
s
=>
result
.
ContainsIgnoreCase
(
s
)))
if
(!
new
[]
{
"200 OK"
,
"connection established"
}.
Any
(
s
=>
result
.
ContainsIgnoreCase
(
s
)))
{
throw
new
Exception
(
"Upstream proxy failed to create a secure tunnel"
);
}
...
...
@@ -125,9 +125,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
client
.
ReceiveTimeout
=
server
.
ConnectionTimeOutSeconds
*
1000
;
client
.
SendTimeout
=
server
.
ConnectionTimeOutSeconds
*
1000
;
client
.
LingerState
=
new
LingerOption
(
true
,
0
);
server
.
ServerConnectionCount
++;
Interlocked
.
Increment
(
ref
server
.
ServerConnectionCountField
);
return
new
TcpConnection
{
...
...
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
View file @
9afb81c6
...
...
@@ -70,8 +70,8 @@ namespace Titanium.Web.Proxy
{
ResponseHeaders
=
new
Dictionary
<
string
,
HttpHeader
>
{
{
"Proxy-Authenticate"
,
new
HttpHeader
(
"Proxy-Authenticate"
,
"Basic realm=\"TitaniumProxy\""
)
},
{
"Proxy-Connection"
,
new
HttpHeader
(
"Proxy-Connection"
,
"close"
)
}
{
"Proxy-Authenticate"
,
new
HttpHeader
(
"Proxy-Authenticate"
,
"Basic realm=\"TitaniumProxy\""
)
},
{
"Proxy-Connection"
,
new
HttpHeader
(
"Proxy-Connection"
,
"close"
)
}
}
};
await
WriteResponseHeaders
(
clientStreamWriter
,
response
);
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Net
;
using
System.Net.Sockets
;
using
System.Security.Authentication
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
System.Linq
;
using
System.Security.Authentication
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
System.Security.Cryptography.X509Certificates
;
namespace
Titanium.Web.Proxy
{
...
...
@@ -35,6 +36,8 @@ namespace Titanium.Web.Proxy
private
Action
<
Exception
>
exceptionFunc
;
private
bool
trustRootCertificate
;
private
int
clientConnectionCountField
;
internal
int
ServerConnectionCountField
;
/// <summary>
/// A object that creates tcp connection to server
...
...
@@ -50,8 +53,7 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Set firefox to use default system proxy
/// </summary>
private
FireFoxProxySettingsManager
firefoxProxySettingsManager
=
new
FireFoxProxySettingsManager
();
private
FireFoxProxySettingsManager
firefoxProxySettingsManager
=
new
FireFoxProxySettingsManager
();
#endif
/// <summary>
...
...
@@ -229,13 +231,13 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Total number of active client connections
/// </summary>
public
int
ClientConnectionCount
{
get
;
private
set
;
}
public
int
ClientConnectionCount
=>
clientConnectionCountField
;
/// <summary>
/// Total number of active server connections
/// </summary>
public
int
ServerConnectionCount
{
get
;
internal
set
;
}
public
int
ServerConnectionCount
=>
ServerConnectionCountField
;
/// <summary>
/// Constructor
...
...
@@ -381,8 +383,7 @@ namespace Titanium.Web.Proxy
#if !DEBUG
firefoxProxySettingsManager
.
AddFirefox
();
#endif
Console
.
WriteLine
(
"Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy"
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
Console
.
WriteLine
(
"Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy"
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
}
/// <summary>
...
...
@@ -596,13 +597,7 @@ namespace Titanium.Web.Proxy
{
Task
.
Run
(
async
()
=>
{
ClientConnectionCount
++;
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
tcpClient
.
LingerState
=
new
LingerOption
(
true
,
0
);
Interlocked
.
Increment
(
ref
clientConnectionCountField
);
try
{
...
...
@@ -617,8 +612,23 @@ namespace Titanium.Web.Proxy
}
finally
{
ClientConnectionCount
--;
tcpClient
?.
Close
();
Interlocked
.
Decrement
(
ref
clientConnectionCountField
);
try
{
if
(
tcpClient
!=
null
)
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
tcpClient
.
LingerState
=
new
LingerOption
(
true
,
0
);
tcpClient
.
Close
();
}
}
catch
{
}
}
});
}
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
9afb81c6
...
...
@@ -6,15 +6,15 @@ using System.Net;
using
System.Net.Security
;
using
System.Net.Sockets
;
using
System.Security.Authentication
;
using
Titanium.Web.Proxy.Exception
s
;
using
System.Threading.Task
s
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Shared
;
using
Titanium.Web.Proxy.Http
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.Shared
;
namespace
Titanium.Web.Proxy
{
...
...
@@ -27,7 +27,9 @@ namespace Titanium.Web.Proxy
//So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
CustomBufferedStream
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
var
disposed
=
false
;
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
clientStream
.
ReadTimeout
=
ConnectionTimeOutSeconds
*
1000
;
clientStream
.
WriteTimeout
=
ConnectionTimeOutSeconds
*
1000
;
...
...
@@ -44,7 +46,6 @@ namespace Titanium.Web.Proxy
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
...
...
@@ -99,7 +100,6 @@ namespace Titanium.Web.Proxy
if
(
await
CheckAuthorization
(
clientStreamWriter
,
connectRequestHeaders
)
==
false
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
...
...
@@ -111,22 +111,23 @@ namespace Titanium.Web.Proxy
{
sslStream
=
new
SslStream
(
clientStream
,
true
);
var
certificate
=
endPoint
.
GenericCertificate
??
CertificateManager
.
CreateCertificate
(
httpRemoteUri
.
Host
,
false
);
var
certificate
=
endPoint
.
GenericCertificate
??
CertificateManager
.
CreateCertificate
(
httpRemoteUri
.
Host
,
false
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SupportedSslProtocols
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
.
Dispose
();
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
}
catch
{
sslStream
?.
Dispose
();
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
...
...
@@ -138,6 +139,7 @@ namespace Titanium.Web.Proxy
{
//Siphon out CONNECT request headers
await
clientStreamReader
.
ReadAndIgnoreAllLinesAsync
();
//write back successfull CONNECT response
await
WriteConnectResponse
(
clientStreamWriter
,
version
);
...
...
@@ -147,18 +149,24 @@ namespace Titanium.Web.Proxy
false
,
clientStream
,
tcpConnectionFactory
);
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
//Now create the request
await
HandleHttpSessionRequest
(
tcpClient
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
httpRemoteUri
.
Scheme
==
Uri
.
UriSchemeHttps
?
httpRemoteUri
.
Host
:
null
,
endPoint
,
connectRequestHeaders
);
disposed
=
await
HandleHttpSessionRequest
(
tcpClient
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
httpRemoteUri
.
Scheme
==
Uri
.
UriSchemeHttps
?
httpRemoteUri
.
Host
:
null
,
endPoint
,
connectRequestHeaders
);
}
catch
(
Exception
)
catch
(
Exception
e
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
ExceptionFunc
(
new
Exception
(
"Error whilst authorizing request"
,
e
));
}
finally
{
if
(!
disposed
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
}
}
}
...
...
@@ -166,7 +174,8 @@ namespace Titanium.Web.Proxy
//So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
private
async
Task
HandleClient
(
TransparentProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
CustomBufferedStream
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
bool
disposed
=
false
;
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
clientStream
.
ReadTimeout
=
ConnectionTimeOutSeconds
*
1000
;
clientStream
.
WriteTimeout
=
ConnectionTimeOutSeconds
*
1000
;
...
...
@@ -174,48 +183,41 @@ namespace Titanium.Web.Proxy
CustomBinaryReader
clientStreamReader
=
null
;
StreamWriter
clientStreamWriter
=
null
;
try
{
if
(
endPoint
.
EnableSsl
)
{
var
sslStream
=
new
SslStream
(
clientStream
,
true
);
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
//implement in future once SNI supported by SSL stream, for now use the same certificate
var
certificate
=
CertificateManager
.
CreateCertificate
(
endPoint
.
GenericCertificateName
,
false
);
try
{
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
//HTTPS server created - we can now decrypt the client's traffic
}
catch
(
Exception
)
{
sslStream
.
Dispose
();
Dispose
(
sslStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
}
else
{
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
}
//now read the request line
var
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
//Now create the request
await
HandleHttpSessionRequest
(
tcpClient
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
disposed
=
await
HandleHttpSessionRequest
(
tcpClient
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
endPoint
.
EnableSsl
?
endPoint
.
GenericCertificateName
:
null
,
endPoint
,
null
);
}
finally
{
if
(!
disposed
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
}
}
}
/// <summary>
/// Create a Server Connection
...
...
@@ -257,9 +259,11 @@ namespace Titanium.Web.Proxy
}
private
async
Task
<
bool
>
HandleHttpSessionRequestInternal
(
TcpConnection
connection
,
SessionEventArgs
args
,
bool
closeConnection
)
private
async
Task
<
bool
>
HandleHttpSessionRequestInternal
(
TcpConnection
connection
,
SessionEventArgs
args
,
bool
closeConnection
)
{
bool
disposed
=
false
;
bool
keepAlive
=
false
;
try
{
args
.
WebSession
.
Request
.
RequestLocked
=
true
;
...
...
@@ -267,12 +271,7 @@ namespace Titanium.Web.Proxy
//If request was cancelled by user then dispose the client
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
{
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
return
false
;
return
true
;
}
//if expect continue is enabled then send the headers first
...
...
@@ -336,47 +335,39 @@ namespace Titanium.Web.Proxy
//If not expectation failed response was returned by server then parse response
if
(!
args
.
WebSession
.
Request
.
ExpectationFailed
)
{
var
result
=
await
HandleHttpSessionResponse
(
args
);
disposed
=
await
HandleHttpSessionResponse
(
args
);
//already disposed inside above method
if
(
result
==
false
)
if
(
disposed
)
{
return
fals
e
;
return
tru
e
;
}
}
//if connection is closing exit
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
==
false
)
{
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
return
true
;
}
if
(!
closeConnection
)
{
keepAlive
=
true
;
return
false
;
}
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
ProxyHttpException
(
"Error occured whilst handling session request (internal)"
,
e
,
args
));
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
return
false
;
return
true
;
}
if
(
closeConnection
)
finally
{
if
(!
disposed
&&
!
keepAlive
)
{
//dispose
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
return
false
;
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
}
}
return
true
;
...
...
@@ -393,13 +384,13 @@ namespace Titanium.Web.Proxy
/// <param name="httpsHostName"></param>
/// <param name="endPoint"></param>
/// <param name="connectHeaders"></param>
/// <param name="customUpStreamHttpProxy"></param>
/// <param name="customUpStreamHttpsProxy"></param>
/// <returns></returns>
private
async
Task
HandleHttpSessionRequest
(
TcpClient
client
,
string
httpCmd
,
Stream
clientStream
,
private
async
Task
<
bool
>
HandleHttpSessionRequest
(
TcpClient
client
,
string
httpCmd
,
Stream
clientStream
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
string
httpsHostName
,
ProxyEndPoint
endPoint
,
List
<
HttpHeader
>
connectHeaders
)
{
bool
disposed
=
false
;
TcpConnection
connection
=
null
;
//Loop through each subsequest request on this particular client connection
...
...
@@ -408,11 +399,6 @@ namespace Titanium.Web.Proxy
{
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
break
;
}
...
...
@@ -458,7 +444,8 @@ namespace Titanium.Web.Proxy
//Read the request headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
clientStreamReader
,
args
.
WebSession
.
Request
.
NonUniqueRequestHeaders
,
args
.
WebSession
.
Request
.
RequestHeaders
);
var
httpRemoteUri
=
new
Uri
(
httpsHostName
==
null
?
httpCmdSplit
[
1
]
var
httpRemoteUri
=
new
Uri
(
httpsHostName
==
null
?
httpCmdSplit
[
1
]
:
string
.
Concat
(
"https://"
,
args
.
WebSession
.
Request
.
Host
??
httpsHostName
,
httpCmdSplit
[
1
]));
args
.
WebSession
.
Request
.
RequestUri
=
httpRemoteUri
;
...
...
@@ -473,11 +460,7 @@ namespace Titanium.Web.Proxy
await
CheckAuthorization
(
clientStreamWriter
,
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
)
==
false
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
args
.
Dispose
();
break
;
}
...
...
@@ -487,15 +470,7 @@ namespace Titanium.Web.Proxy
//If user requested interception do it
if
(
BeforeRequest
!=
null
)
{
var
invocationList
=
BeforeRequest
.
GetInvocationList
();
var
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
var
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
SessionEventArgs
,
Task
>)
invocationList
[
i
])(
this
,
args
);
}
await
Task
.
WhenAll
(
handlerTasks
);
await
BeforeRequest
.
InvokeParallelAsync
(
this
,
args
);
}
//if upgrading to websocket then relay the requet without reading the contents
...
...
@@ -506,11 +481,7 @@ namespace Titanium.Web.Proxy
httpCmd
,
httpVersion
,
args
.
WebSession
.
Request
.
RequestHeaders
,
args
.
IsHttps
,
clientStream
,
tcpConnectionFactory
);
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
args
.
Dispose
();
break
;
}
...
...
@@ -520,50 +491,46 @@ namespace Titanium.Web.Proxy
}
//construct the web request that we are going to issue on behalf of the client.
var
result
=
await
HandleHttpSessionRequestInternal
(
connection
,
args
,
false
);
disposed
=
await
HandleHttpSessionRequestInternal
(
connection
,
args
,
false
);
if
(
result
==
false
)
if
(
disposed
)
{
//already disposed inside above method
args
.
Dispose
();
break
;
}
if
(
args
.
WebSession
.
Request
.
CancelRequest
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
args
.
Dispose
();
break
;
}
//if connection is closing exit
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
==
false
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
args
.
Dispose
();
break
;
}
args
.
Dispose
();
// read the next request
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
}
catch
(
Exception
e
)
{
ExceptionFunc
(
new
ProxyHttpException
(
"Error occured whilst handling session request"
,
e
,
args
));
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
break
;
}
}
if
(!
disposed
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
connection
);
}
return
true
;
}
/// <summary>
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
9afb81c6
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Compression
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Compression
;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network.Tcp
;
namespace
Titanium.Web.Proxy
...
...
@@ -22,7 +23,7 @@ namespace Titanium.Web.Proxy
/// Called asynchronously when a request was successfully and we received the response
/// </summary>
/// <param name="args"></param>
/// <returns>true if
no errors
</returns>
/// <returns>true if
client/server connection was terminated (and disposed)
</returns>
private
async
Task
<
bool
>
HandleHttpSessionResponse
(
SessionEventArgs
args
)
{
try
...
...
@@ -40,28 +41,20 @@ namespace Titanium.Web.Proxy
//If user requested call back then do it
if
(
BeforeResponse
!=
null
&&
!
args
.
WebSession
.
Response
.
ResponseLocked
)
{
Delegate
[]
invocationList
=
BeforeResponse
.
GetInvocationList
();
Task
[]
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
handlerTasks
[
i
]
=
((
Func
<
object
,
SessionEventArgs
,
Task
>)
invocationList
[
i
])(
this
,
args
);
}
await
Task
.
WhenAll
(
handlerTasks
);
await
BeforeResponse
.
InvokeParallelAsync
(
this
,
args
);
}
if
(
args
.
ReRequest
)
{
if
(
args
.
WebSession
.
ServerConnection
!=
null
)
if
(
args
.
WebSession
.
ServerConnection
!=
null
)
{
args
.
WebSession
.
ServerConnection
.
Dispose
();
ServerConnectionCount
--
;
Interlocked
.
Decrement
(
ref
ServerConnectionCountField
)
;
}
var
connection
=
await
GetServerConnection
(
args
);
var
result
=
await
HandleHttpSessionRequestInternal
(
null
,
args
,
true
);
return
result
;
var
disposed
=
await
HandleHttpSessionRequestInternal
(
null
,
args
,
true
);
return
disposed
;
}
args
.
WebSession
.
Response
.
ResponseLocked
=
true
;
...
...
@@ -137,12 +130,10 @@ namespace Titanium.Web.Proxy
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
return
fals
e
;
return
tru
e
;
}
args
.
Dispose
();
return
true
;
return
false
;
}
/// <summary>
...
...
@@ -240,15 +231,17 @@ namespace Titanium.Web.Proxy
StreamWriter
clientStreamWriter
,
TcpConnection
serverConnection
)
{
ServerConnectionCount
--;
clientStream
?.
Close
();
clientStream
?.
Dispose
();
clientStreamReader
?.
Dispose
();
clientStreamWriter
?.
Dispose
();
serverConnection
?.
Dispose
();
if
(
serverConnection
!=
null
)
{
serverConnection
.
Dispose
();
Interlocked
.
Decrement
(
ref
ServerConnectionCountField
);
}
}
}
}
Titanium.Web.Proxy/Shared/ProxyConstants.cs
View file @
9afb81c6
...
...
@@ -7,9 +7,9 @@ namespace Titanium.Web.Proxy.Shared
/// </summary>
internal
class
ProxyConstants
{
internal
static
readonly
char
[]
SpaceSplit
=
{
' '
};
internal
static
readonly
char
[]
ColonSplit
=
{
':'
};
internal
static
readonly
char
[]
SemiColonSplit
=
{
';'
};
internal
static
readonly
char
[]
SpaceSplit
=
{
' '
};
internal
static
readonly
char
[]
ColonSplit
=
{
':'
};
internal
static
readonly
char
[]
SemiColonSplit
=
{
';'
};
internal
static
readonly
byte
[]
NewLineBytes
=
Encoding
.
ASCII
.
GetBytes
(
NewLine
);
...
...
Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
9afb81c6
...
...
@@ -73,6 +73,7 @@
<Compile
Include=
"EventArguments\CertificateSelectionEventArgs.cs"
/>
<Compile
Include=
"EventArguments\CertificateValidationEventArgs.cs"
/>
<Compile
Include=
"Extensions\ByteArrayExtensions.cs"
/>
<Compile
Include=
"Extensions\FuncExtensions.cs"
/>
<Compile
Include=
"Extensions\StringExtensions.cs"
/>
<Compile
Include=
"Helpers\CustomBufferedStream.cs"
/>
<Compile
Include=
"Helpers\Network.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