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
ebed40b1
Unverified
Commit
ebed40b1
authored
Nov 17, 2019
by
honfika
Committed by
GitHub
Nov 17, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #665 from justcoding121/beta
Stable
parents
d8df61ba
3b807dad
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
38 changed files
with
566 additions
and
704 deletions
+566
-704
LimitedStream.cs
src/Titanium.Web.Proxy/EventArguments/LimitedStream.cs
+8
-7
SessionEventArgs.cs
src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+35
-41
SessionEventArgsBase.cs
...Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
+12
-11
TunnelConnectEventArgs.cs
...tanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
+4
-2
ExplicitClientHandler.cs
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
+11
-19
HttpClientStream.cs
src/Titanium.Web.Proxy/Helpers/HttpClientStream.cs
+2
-2
HttpHelper.cs
src/Titanium.Web.Proxy/Helpers/HttpHelper.cs
+6
-6
HttpServerStream.cs
src/Titanium.Web.Proxy/Helpers/HttpServerStream.cs
+2
-2
HttpStream.cs
src/Titanium.Web.Proxy/Helpers/HttpStream.cs
+338
-44
HttpWriter.cs
src/Titanium.Web.Proxy/Helpers/HttpWriter.cs
+0
-346
WinHttpWebProxyFinder.cs
...tanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
+1
-1
HttpWebClient.cs
src/Titanium.Web.Proxy/Http/HttpWebClient.cs
+2
-2
Http2Helper.cs
src/Titanium.Web.Proxy/Http2/Http2Helper.cs
+4
-1
ExternalProxy.cs
src/Titanium.Web.Proxy/Models/ExternalProxy.cs
+1
-1
IExternalProxy.cs
src/Titanium.Web.Proxy/Models/IExternalProxy.cs
+37
-0
DebugCustomBufferedStream.cs
src/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs
+0
-74
ProxyClient.cs
src/Titanium.Web.Proxy/Network/ProxyClient.cs
+0
-34
TcpClientConnection.cs
src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs
+0
-1
TcpConnectionFactory.cs
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+23
-19
TcpServerConnection.cs
src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
+8
-16
ProxyServer.cs
src/Titanium.Web.Proxy/ProxyServer.cs
+7
-14
RequestHandler.cs
src/Titanium.Web.Proxy/RequestHandler.cs
+9
-13
ResponseHandler.cs
src/Titanium.Web.Proxy/ResponseHandler.cs
+5
-5
CopyStream.cs
src/Titanium.Web.Proxy/StreamExtended/Network/CopyStream.cs
+5
-4
IHttpStreamReader.cs
...ium.Web.Proxy/StreamExtended/Network/IHttpStreamReader.cs
+12
-0
IHttpStreamWriter.cs
...ium.Web.Proxy/StreamExtended/Network/IHttpStreamWriter.cs
+7
-3
PeekStreamReader.cs
...nium.Web.Proxy/StreamExtended/Network/PeekStreamReader.cs
+1
-1
SslTools.cs
src/Titanium.Web.Proxy/StreamExtended/SslTools.cs
+9
-9
Titanium.Web.Proxy.Mono.csproj
src/Titanium.Web.Proxy/Titanium.Web.Proxy.Mono.csproj
+1
-1
Titanium.Web.Proxy.NetCore.csproj
src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
+1
-1
Titanium.Web.Proxy.csproj
src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+1
-1
Titanium.Web.Proxy.nuspec
src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
+2
-2
TransparentClientHandler.cs
src/Titanium.Web.Proxy/TransparentClientHandler.cs
+5
-13
WebSocketHandler.cs
src/Titanium.Web.Proxy/WebSocketHandler.cs
+3
-4
WinAuthHandler.cs
src/Titanium.Web.Proxy/WinAuthHandler.cs
+1
-1
NestedProxyTests.cs
...s/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs
+1
-1
Titanium.Web.Proxy.IntegrationTests.csproj
...tegrationTests/Titanium.Web.Proxy.IntegrationTests.csproj
+1
-1
Titanium.Web.Proxy.UnitTests.csproj
...m.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
+1
-1
No files found.
src/Titanium.Web.Proxy/EventArguments/LimitedStream.cs
View file @
ebed40b1
...
...
@@ -3,6 +3,7 @@ using System.Globalization;
using
System.IO
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Exceptions
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.StreamExtended.BufferPool
;
using
Titanium.Web.Proxy.StreamExtended.Network
;
...
...
@@ -11,16 +12,16 @@ namespace Titanium.Web.Proxy.EventArguments
internal
class
LimitedStream
:
Stream
{
private
readonly
IBufferPool
bufferPool
;
private
readonly
CustomBufferedStream
baseStream
;
private
readonly
IHttpStreamReader
baseReader
;
private
readonly
bool
isChunked
;
private
long
bytesRemaining
;
private
bool
readChunkTrail
;
internal
LimitedStream
(
CustomBufferedStream
baseStream
,
IBufferPool
bufferPool
,
bool
isChunked
,
internal
LimitedStream
(
IHttpStreamReader
baseStream
,
IBufferPool
bufferPool
,
bool
isChunked
,
long
contentLength
)
{
this
.
base
Stream
=
baseStream
;
this
.
base
Reader
=
baseStream
;
this
.
bufferPool
=
bufferPool
;
this
.
isChunked
=
isChunked
;
bytesRemaining
=
isChunked
...
...
@@ -49,12 +50,12 @@ namespace Titanium.Web.Proxy.EventArguments
if
(
readChunkTrail
)
{
// read the chunk trail of the previous chunk
string
?
s
=
base
Stream
.
ReadLineAsync
().
Result
;
string
?
s
=
base
Reader
.
ReadLineAsync
().
Result
;
}
readChunkTrail
=
true
;
string
?
chunkHead
=
base
Stream
.
ReadLineAsync
().
Result
!;
string
?
chunkHead
=
base
Reader
.
ReadLineAsync
().
Result
!;
int
idx
=
chunkHead
.
IndexOf
(
";"
,
StringComparison
.
Ordinal
);
if
(
idx
>=
0
)
{
...
...
@@ -73,7 +74,7 @@ namespace Titanium.Web.Proxy.EventArguments
bytesRemaining
=
-
1
;
// chunk trail
var
task
=
base
Stream
.
ReadLineAsync
();
var
task
=
base
Reader
.
ReadLineAsync
();
if
(!
task
.
IsCompleted
)
task
.
AsTask
().
Wait
();
}
...
...
@@ -119,7 +120,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
int
toRead
=
(
int
)
Math
.
Min
(
count
,
bytesRemaining
);
int
res
=
base
Stream
.
Read
(
buffer
,
offset
,
toRead
);
int
res
=
base
Reader
.
Read
(
buffer
,
offset
,
toRead
);
bytesRemaining
-=
res
;
if
(
res
==
0
)
...
...
src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
ebed40b1
...
...
@@ -10,6 +10,7 @@ using Titanium.Web.Proxy.Http;
using
Titanium.Web.Proxy.Http.Responses
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.StreamExtended.Network
;
namespace
Titanium.Web.Proxy.EventArguments
...
...
@@ -22,8 +23,6 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
class
SessionEventArgs
:
SessionEventArgsBase
{
private
static
readonly
byte
[]
emptyData
=
new
byte
[
0
];
/// <summary>
/// Backing field for corresponding public property
/// </summary>
...
...
@@ -37,8 +36,8 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// Constructor to initialize the proxy
/// </summary>
internal
SessionEventArgs
(
ProxyServer
server
,
ProxyEndPoint
endPoint
,
ProxyClient
proxyClient
,
ConnectRequest
?
connectRequest
,
CancellationTokenSource
cancellationTokenSource
)
:
base
(
server
,
endPoint
,
proxyClient
,
connectRequest
,
new
Request
(),
cancellationTokenSource
)
internal
SessionEventArgs
(
ProxyServer
server
,
ProxyEndPoint
endPoint
,
TcpClientConnection
clientConnection
,
HttpClientStream
clientStream
,
ConnectRequest
?
connectRequest
,
CancellationTokenSource
cancellationTokenSource
)
:
base
(
server
,
endPoint
,
clientConnection
,
clientStream
,
connectRequest
,
new
Request
(),
cancellationTokenSource
)
{
}
...
...
@@ -66,14 +65,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
event
EventHandler
<
MultipartRequestPartSentEventArgs
>?
MultipartRequestPartSent
;
private
CustomBufferedStream
getStreamReader
(
bool
isRequest
)
{
return
isRequest
?
ProxyClient
.
ClientStream
:
HttpClient
.
Connection
.
Stream
;
}
private
HttpWriter
getStreamWriter
(
bool
isRequest
)
private
HttpStream
getStream
(
bool
isRequest
)
{
return
isRequest
?
(
Http
Writer
)
ProxyClient
.
ClientStreamWriter
:
HttpClient
.
Connection
.
StreamWriter
;
return
isRequest
?
(
Http
Stream
)
ClientStream
:
HttpClient
.
Connection
.
Stream
;
}
/// <summary>
...
...
@@ -110,7 +104,10 @@ namespace Titanium.Web.Proxy.EventArguments
else
{
var
body
=
await
readBodyAsync
(
true
,
cancellationToken
);
request
.
Body
=
body
;
if
(!
request
.
BodyAvailable
)
{
request
.
Body
=
body
;
}
// Now set the flag to true
// So that next time we can deliver body from cache
...
...
@@ -182,7 +179,10 @@ namespace Titanium.Web.Proxy.EventArguments
else
{
var
body
=
await
readBodyAsync
(
false
,
cancellationToken
);
response
.
Body
=
body
;
if
(!
response
.
BodyAvailable
)
{
response
.
Body
=
body
;
}
// Now set the flag to true
// So that next time we can deliver body from cache
...
...
@@ -193,21 +193,19 @@ namespace Titanium.Web.Proxy.EventArguments
private
async
Task
<
byte
[
]>
readBodyAsync
(
bool
isRequest
,
CancellationToken
cancellationToken
)
{
using
(
var
bodyStream
=
new
MemoryStream
())
{
var
writer
=
new
HttpWriter
(
bodyStream
,
BufferPool
);
if
(
isRequest
)
{
await
CopyRequestBodyAsync
(
writer
,
TransformationMode
.
Uncompress
,
cancellationToken
);
}
else
{
await
CopyResponseBodyAsync
(
writer
,
TransformationMode
.
Uncompress
,
cancellationToken
);
}
using
var
bodyStream
=
new
MemoryStream
();
using
var
http
=
new
HttpStream
(
bodyStream
,
BufferPool
);
return
bodyStream
.
ToArray
();
if
(
isRequest
)
{
await
CopyRequestBodyAsync
(
http
,
TransformationMode
.
Uncompress
,
cancellationToken
);
}
else
{
await
CopyResponseBodyAsync
(
http
,
TransformationMode
.
Uncompress
,
cancellationToken
);
}
return
bodyStream
.
ToArray
();
}
/// <summary>
...
...
@@ -225,18 +223,16 @@ namespace Titanium.Web.Proxy.EventArguments
return
;
}
using
(
var
bodyStream
=
new
MemoryStream
())
{
var
writer
=
new
HttpWriter
(
bodyStream
,
BufferPool
);
await
copyBodyAsync
(
isRequest
,
true
,
writer
,
TransformationMode
.
None
,
null
,
cancellationToken
);
}
using
var
bodyStream
=
new
MemoryStream
();
using
var
http
=
new
HttpStream
(
bodyStream
,
BufferPool
);
await
copyBodyAsync
(
isRequest
,
true
,
http
,
TransformationMode
.
None
,
null
,
cancellationToken
);
}
/// <summary>
/// This is called when the request is PUT/POST/PATCH to read the body
/// </summary>
/// <returns></returns>
internal
async
Task
CopyRequestBodyAsync
(
Http
Writer
writer
,
TransformationMode
transformation
,
CancellationToken
cancellationToken
)
internal
async
Task
CopyRequestBodyAsync
(
IHttpStream
Writer
writer
,
TransformationMode
transformation
,
CancellationToken
cancellationToken
)
{
var
request
=
HttpClient
.
Request
;
...
...
@@ -245,7 +241,7 @@ namespace Titanium.Web.Proxy.EventArguments
// send the request body bytes to server
if
(
contentLength
>
0
&&
hasMulipartEventSubscribers
&&
request
.
IsMultipartFormData
)
{
var
reader
=
getStream
Reader
(
true
);
var
reader
=
getStream
(
true
);
var
boundary
=
HttpHelper
.
GetBoundaryFromContentType
(
request
.
ContentType
);
using
(
var
copyStream
=
new
CopyStream
(
reader
,
writer
,
BufferPool
))
...
...
@@ -275,14 +271,14 @@ namespace Titanium.Web.Proxy.EventArguments
}
}
internal
async
Task
CopyResponseBodyAsync
(
Http
Writer
writer
,
TransformationMode
transformation
,
CancellationToken
cancellationToken
)
internal
async
Task
CopyResponseBodyAsync
(
IHttpStream
Writer
writer
,
TransformationMode
transformation
,
CancellationToken
cancellationToken
)
{
await
copyBodyAsync
(
false
,
false
,
writer
,
transformation
,
OnDataReceived
,
cancellationToken
);
}
private
async
Task
copyBodyAsync
(
bool
isRequest
,
bool
useOriginalHeaderValues
,
Http
Writer
writer
,
TransformationMode
transformation
,
Action
<
byte
[],
int
,
int
>?
onCopy
,
CancellationToken
cancellationToken
)
private
async
Task
copyBodyAsync
(
bool
isRequest
,
bool
useOriginalHeaderValues
,
IHttpStream
Writer
writer
,
TransformationMode
transformation
,
Action
<
byte
[],
int
,
int
>?
onCopy
,
CancellationToken
cancellationToken
)
{
var
stream
=
getStream
Reader
(
isRequest
);
var
stream
=
getStream
(
isRequest
);
var
requestResponse
=
isRequest
?
(
RequestResponseBase
)
HttpClient
.
Request
:
HttpClient
.
Response
;
...
...
@@ -309,10 +305,8 @@ namespace Titanium.Web.Proxy.EventArguments
try
{
using
(
var
bufStream
=
new
CustomBufferedStream
(
s
,
BufferPool
,
true
))
{
await
writer
.
CopyBodyAsync
(
bufStream
,
false
,
-
1
,
onCopy
,
cancellationToken
);
}
var
http
=
new
HttpStream
(
s
,
BufferPool
,
true
);
await
writer
.
CopyBodyAsync
(
http
,
false
,
-
1
,
onCopy
,
cancellationToken
);
}
finally
{
...
...
@@ -595,7 +589,7 @@ namespace Titanium.Web.Proxy.EventArguments
var
response
=
new
RedirectResponse
();
response
.
HttpVersion
=
HttpClient
.
Request
.
HttpVersion
;
response
.
Headers
.
AddHeader
(
KnownHeaders
.
Location
,
url
);
response
.
Body
=
emptyData
;
response
.
Body
=
Array
.
Empty
<
byte
>()
;
Respond
(
response
,
closeServerConnection
);
}
...
...
src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs
View file @
ebed40b1
...
...
@@ -26,7 +26,12 @@ namespace Titanium.Web.Proxy.EventArguments
internal
TcpServerConnection
ServerConnection
=>
HttpClient
.
Connection
;
internal
TcpClientConnection
ClientConnection
=>
ProxyClient
.
Connection
;
/// <summary>
/// Holds a reference to client
/// </summary>
internal
TcpClientConnection
ClientConnection
{
get
;
}
internal
HttpClientStream
ClientStream
{
get
;
}
protected
readonly
IBufferPool
BufferPool
;
protected
readonly
ExceptionHandler
ExceptionFunc
;
...
...
@@ -41,7 +46,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
/// </summary>
private
protected
SessionEventArgsBase
(
ProxyServer
server
,
ProxyEndPoint
endPoint
,
ProxyClient
proxyClient
,
ConnectRequest
?
connectRequest
,
Request
request
,
CancellationTokenSource
cancellationTokenSource
)
TcpClientConnection
clientConnection
,
HttpClientStream
clientStream
,
ConnectRequest
?
connectRequest
,
Request
request
,
CancellationTokenSource
cancellationTokenSource
)
{
BufferPool
=
server
.
BufferPool
;
ExceptionFunc
=
server
.
ExceptionFunc
;
...
...
@@ -49,17 +54,13 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource
=
cancellationTokenSource
;
ProxyClient
=
proxyClient
;
HttpClient
=
new
HttpWebClient
(
connectRequest
,
request
,
new
Lazy
<
int
>(()
=>
ProxyClient
.
Connection
.
GetProcessId
(
endPoint
)));
ClientConnection
=
clientConnection
;
ClientStream
=
clientStream
;
HttpClient
=
new
HttpWebClient
(
connectRequest
,
request
,
new
Lazy
<
int
>(()
=>
clientConnection
.
GetProcessId
(
endPoint
)));
LocalEndPoint
=
endPoint
;
EnableWinAuth
=
server
.
EnableWinAuth
&&
isWindowsAuthenticationSupported
;
}
/// <summary>
/// Holds a reference to client
/// </summary>
internal
ProxyClient
ProxyClient
{
get
;
}
/// <summary>
/// Returns a user data for this request/response session which is
/// same as the user data of HttpClient.
...
...
@@ -93,7 +94,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// Client End Point.
/// </summary>
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
ProxyClient
.
Connection
.
RemoteEndPoint
;
public
IPEndPoint
ClientEndPoint
=>
(
IPEndPoint
)
Client
Connection
.
RemoteEndPoint
;
/// <summary>
/// The web client used to communicate with server for this session.
...
...
@@ -106,7 +107,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// Are we using a custom upstream HTTP(S) proxy?
/// </summary>
public
ExternalProxy
?
CustomUpStreamProxyUsed
{
get
;
internal
set
;
}
public
I
ExternalProxy
?
CustomUpStreamProxyUsed
{
get
;
internal
set
;
}
/// <summary>
/// Local endpoint via which we make the request.
...
...
src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs
View file @
ebed40b1
using
System
;
using
System.Threading
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Http
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.StreamExtended.Network
;
namespace
Titanium.Web.Proxy.EventArguments
...
...
@@ -15,8 +17,8 @@ namespace Titanium.Web.Proxy.EventArguments
private
bool
?
isHttpsConnect
;
internal
TunnelConnectSessionEventArgs
(
ProxyServer
server
,
ProxyEndPoint
endPoint
,
ConnectRequest
connectRequest
,
ProxyClient
proxyClient
,
CancellationTokenSource
cancellationTokenSource
)
:
base
(
server
,
endPoint
,
proxyClient
,
connectRequest
,
connectRequest
,
cancellationTokenSource
)
TcpClientConnection
clientConnection
,
HttpClientStream
clientStream
,
CancellationTokenSource
cancellationTokenSource
)
:
base
(
server
,
endPoint
,
clientConnection
,
clientStream
,
connectRequest
,
connectRequest
,
cancellationTokenSource
)
{
}
...
...
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
View file @
ebed40b1
...
...
@@ -36,8 +36,7 @@ namespace Titanium.Web.Proxy
var
cancellationTokenSource
=
new
CancellationTokenSource
();
var
cancellationToken
=
cancellationTokenSource
.
Token
;
var
clientStream
=
new
CustomBufferedStream
(
clientConnection
.
GetStream
(),
BufferPool
);
var
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferPool
);
var
clientStream
=
new
HttpClientStream
(
clientConnection
.
GetStream
(),
BufferPool
);
Task
<
TcpServerConnection
>?
prefetchConnectionTask
=
null
;
bool
closeServerConnection
=
false
;
...
...
@@ -70,7 +69,7 @@ namespace Titanium.Web.Proxy
await
HeaderParser
.
ReadHeaders
(
clientStream
,
connectRequest
.
Headers
,
cancellationToken
);
connectArgs
=
new
TunnelConnectSessionEventArgs
(
this
,
endPoint
,
connectRequest
,
new
ProxyClient
(
clientConnection
,
clientStream
,
clientStreamWriter
)
,
cancellationTokenSource
);
clientConnection
,
clientStream
,
cancellationTokenSource
);
clientStream
.
DataRead
+=
(
o
,
args
)
=>
connectArgs
.
OnDataSent
(
args
.
Buffer
,
args
.
Offset
,
args
.
Count
);
clientStream
.
DataWrite
+=
(
o
,
args
)
=>
connectArgs
.
OnDataReceived
(
args
.
Buffer
,
args
.
Offset
,
args
.
Count
);
...
...
@@ -92,7 +91,7 @@ namespace Titanium.Web.Proxy
}
// send the response
await
clientStream
Writer
.
WriteResponseAsync
(
connectArgs
.
HttpClient
.
Response
,
await
clientStream
.
WriteResponseAsync
(
connectArgs
.
HttpClient
.
Response
,
cancellationToken
:
cancellationToken
);
return
;
}
...
...
@@ -102,7 +101,7 @@ namespace Titanium.Web.Proxy
await
endPoint
.
InvokeBeforeTunnelConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
);
// send the response
await
clientStream
Writer
.
WriteResponseAsync
(
connectArgs
.
HttpClient
.
Response
,
await
clientStream
.
WriteResponseAsync
(
connectArgs
.
HttpClient
.
Response
,
cancellationToken
:
cancellationToken
);
return
;
}
...
...
@@ -115,14 +114,13 @@ namespace Titanium.Web.Proxy
response
.
Headers
.
FixProxyHeaders
();
connectArgs
.
HttpClient
.
Response
=
response
;
await
clientStream
Writer
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
await
clientStream
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
var
clientHelloInfo
=
await
SslTools
.
PeekClientHello
(
clientStream
,
BufferPool
,
cancellationToken
);
bool
isClientHello
=
clientHelloInfo
!=
null
;
if
(
clientHelloInfo
!=
null
)
{
connectRequest
.
IsHttps
=
true
;
connectRequest
.
TunnelType
=
TunnelType
.
Https
;
connectRequest
.
ClientHelloInfo
=
clientHelloInfo
;
}
...
...
@@ -131,6 +129,7 @@ namespace Titanium.Web.Proxy
if
(
decryptSsl
&&
clientHelloInfo
!=
null
)
{
connectRequest
.
IsHttps
=
true
;
// todo: move this line to the previous "if"
clientConnection
.
SslProtocol
=
clientHelloInfo
.
SslProtocol
;
bool
http2Supported
=
false
;
...
...
@@ -216,10 +215,9 @@ namespace Titanium.Web.Proxy
#endif
// HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBuffered
Stream
(
sslStream
,
BufferPool
);
clientStream
=
new
HttpClient
Stream
(
sslStream
,
BufferPool
);
clientStream
.
DataRead
+=
(
o
,
args
)
=>
connectArgs
.
OnDecryptedDataSent
(
args
.
Buffer
,
args
.
Offset
,
args
.
Count
);
clientStream
.
DataWrite
+=
(
o
,
args
)
=>
connectArgs
.
OnDecryptedDataReceived
(
args
.
Buffer
,
args
.
Offset
,
args
.
Count
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferPool
);
}
catch
(
Exception
e
)
{
...
...
@@ -274,7 +272,7 @@ namespace Titanium.Web.Proxy
{
// clientStream.Available should be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
,
cancellationToken
);
await
connection
.
Stream
Writer
.
WriteAsync
(
data
,
0
,
available
,
true
,
cancellationToken
);
await
connection
.
Stream
.
WriteAsync
(
data
,
0
,
available
,
true
,
cancellationToken
);
}
finally
{
...
...
@@ -335,9 +333,9 @@ namespace Titanium.Web.Proxy
{
#if NETSTANDARD2_1
var
connectionPreface
=
new
ReadOnlyMemory
<
byte
>(
Http2Helper
.
ConnectionPreface
);
await
connection
.
Stream
Writer
.
WriteAsync
(
connectionPreface
,
cancellationToken
);
await
connection
.
Stream
.
WriteAsync
(
connectionPreface
,
cancellationToken
);
await
Http2Helper
.
SendHttp2
(
clientStream
,
connection
.
Stream
,
()
=>
new
SessionEventArgs
(
this
,
endPoint
,
new
ProxyClient
(
clientConnection
,
clientStream
,
clientStreamWriter
)
,
connectArgs
?.
HttpClient
.
ConnectRequest
,
cancellationTokenSource
)
()
=>
new
SessionEventArgs
(
this
,
endPoint
,
clientConnection
,
clientStream
,
connectArgs
?.
HttpClient
.
ConnectRequest
,
cancellationTokenSource
)
{
UserData
=
connectArgs
?.
UserData
},
...
...
@@ -356,8 +354,7 @@ namespace Titanium.Web.Proxy
calledRequestHandler
=
true
;
// Now create the request
await
handleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
clientStreamWriter
,
cancellationTokenSource
,
connectArgs
,
prefetchConnectionTask
);
await
handleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
cancellationTokenSource
,
connectArgs
,
prefetchConnectionTask
);
}
catch
(
ProxyException
e
)
{
...
...
@@ -388,11 +385,6 @@ namespace Titanium.Web.Proxy
sslStream
?.
Dispose
();
clientStream
.
Dispose
();
if
(!
cancellationTokenSource
.
IsCancellationRequested
)
{
cancellationTokenSource
.
Cancel
();
}
}
}
}
...
...
src/Titanium.Web.Proxy/Helpers/Http
ResponseWriter
.cs
→
src/Titanium.Web.Proxy/Helpers/Http
ClientStream
.cs
View file @
ebed40b1
...
...
@@ -7,9 +7,9 @@ using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace
Titanium.Web.Proxy.Helpers
{
internal
sealed
class
Http
ResponseWriter
:
HttpWriter
internal
sealed
class
Http
ClientStream
:
HttpStream
{
internal
Http
ResponseWriter
(
Stream
stream
,
IBufferPool
bufferPool
)
internal
Http
ClientStream
(
Stream
stream
,
IBufferPool
bufferPool
)
:
base
(
stream
,
bufferPool
)
{
}
...
...
src/Titanium.Web.Proxy/Helpers/HttpHelper.cs
View file @
ebed40b1
...
...
@@ -170,18 +170,18 @@ namespace Titanium.Web.Proxy.Helpers
/// Determines whether is connect method.
/// </summary>
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
internal
static
Task
<
int
>
IsConnectMethod
(
CustomBufferedStream
clientStream
Reader
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
internal
static
Task
<
int
>
IsConnectMethod
(
IPeekStream
http
Reader
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
{
return
startsWith
(
clientStream
Reader
,
bufferPool
,
"CONNECT"
,
cancellationToken
);
return
startsWith
(
http
Reader
,
bufferPool
,
"CONNECT"
,
cancellationToken
);
}
/// <summary>
/// Determines whether is pri method (HTTP/2).
/// </summary>
/// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns>
internal
static
Task
<
int
>
IsPriMethod
(
CustomBufferedStream
clientStream
Reader
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
internal
static
Task
<
int
>
IsPriMethod
(
IPeekStream
http
Reader
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
{
return
startsWith
(
clientStream
Reader
,
bufferPool
,
"PRI"
,
cancellationToken
);
return
startsWith
(
http
Reader
,
bufferPool
,
"PRI"
,
cancellationToken
);
}
/// <summary>
...
...
@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </returns>
private
static
async
Task
<
int
>
startsWith
(
CustomBufferedStream
clientStream
Reader
,
IBufferPool
bufferPool
,
string
expectedStart
,
CancellationToken
cancellationToken
=
default
)
private
static
async
Task
<
int
>
startsWith
(
IPeekStream
http
Reader
,
IBufferPool
bufferPool
,
string
expectedStart
,
CancellationToken
cancellationToken
=
default
)
{
const
int
lengthToCheck
=
10
;
if
(
bufferPool
.
BufferSize
<
lengthToCheck
)
...
...
@@ -205,7 +205,7 @@ namespace Titanium.Web.Proxy.Helpers
int
i
=
0
;
while
(
i
<
lengthToCheck
)
{
int
peeked
=
await
clientStream
Reader
.
PeekBytesAsync
(
buffer
,
i
,
i
,
lengthToCheck
-
i
,
cancellationToken
);
int
peeked
=
await
http
Reader
.
PeekBytesAsync
(
buffer
,
i
,
i
,
lengthToCheck
-
i
,
cancellationToken
);
if
(
peeked
<=
0
)
return
-
1
;
...
...
src/Titanium.Web.Proxy/Helpers/Http
RequestWriter
.cs
→
src/Titanium.Web.Proxy/Helpers/Http
ServerStream
.cs
View file @
ebed40b1
...
...
@@ -6,9 +6,9 @@ using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace
Titanium.Web.Proxy.Helpers
{
internal
sealed
class
Http
RequestWriter
:
HttpWriter
internal
sealed
class
Http
ServerStream
:
HttpStream
{
internal
Http
RequestWriter
(
Stream
stream
,
IBufferPool
bufferPool
)
internal
Http
ServerStream
(
Stream
stream
,
IBufferPool
bufferPool
)
:
base
(
stream
,
bufferPool
)
{
}
...
...
src/Titanium.Web.Proxy/
StreamExtended/Network/CustomBuffered
Stream.cs
→
src/Titanium.Web.Proxy/
Helpers/Http
Stream.cs
View file @
ebed40b1
This diff is collapsed.
Click to expand it.
src/Titanium.Web.Proxy/Helpers/HttpWriter.cs
deleted
100644 → 0
View file @
d8df61ba
This diff is collapsed.
Click to expand it.
src/Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
View file @
ebed40b1
...
...
@@ -95,7 +95,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return
true
;
}
public
ExternalProxy
?
GetProxy
(
Uri
destination
)
public
I
ExternalProxy
?
GetProxy
(
Uri
destination
)
{
if
(
GetAutoProxies
(
destination
,
out
var
proxies
))
{
...
...
src/Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
ebed40b1
...
...
@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy.Http
bool
useUpstreamProxy
=
upstreamProxy
!=
null
&&
Connection
.
IsHttps
==
false
;
var
writer
=
Connection
.
StreamWriter
;
var
serverStream
=
Connection
.
Stream
;
string
url
;
if
(
useUpstreamProxy
||
isTransparent
)
...
...
@@ -153,7 +153,7 @@ namespace Titanium.Web.Proxy.Http
headerBuilder
.
WriteLine
();
await
writer
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
await
serverStream
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
if
(
enable100ContinueBehaviour
&&
Request
.
ExpectContinue
)
{
...
...
src/Titanium.Web.Proxy/Http2/Http2Helper.cs
View file @
ebed40b1
...
...
@@ -389,7 +389,10 @@ namespace Titanium.Web.Proxy.Http2
}
}
rr
.
Body
=
body
;
if
(!
rr
.
BodyAvailable
)
{
rr
.
Body
=
body
;
}
}
rr
.
IsBodyRead
=
true
;
...
...
src/Titanium.Web.Proxy/Models/ExternalProxy.cs
View file @
ebed40b1
...
...
@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Models
/// <summary>
/// An upstream proxy this proxy uses if any.
/// </summary>
public
class
ExternalProxy
public
class
ExternalProxy
:
IExternalProxy
{
private
static
readonly
Lazy
<
NetworkCredential
>
defaultCredentials
=
new
Lazy
<
NetworkCredential
>(()
=>
CredentialCache
.
DefaultNetworkCredentials
);
...
...
src/Titanium.Web.Proxy/Models/IExternalProxy.cs
0 → 100644
View file @
ebed40b1
namespace
Titanium.Web.Proxy.Models
{
public
interface
IExternalProxy
{
/// <summary>
/// Use default windows credentials?
/// </summary>
bool
UseDefaultCredentials
{
get
;
set
;
}
/// <summary>
/// Bypass this proxy for connections to localhost?
/// </summary>
bool
BypassLocalhost
{
get
;
set
;
}
/// <summary>
/// Username.
/// </summary>
string
?
UserName
{
get
;
set
;
}
/// <summary>
/// Password.
/// </summary>
string
?
Password
{
get
;
set
;
}
/// <summary>
/// Host name.
/// </summary>
string
HostName
{
get
;
set
;
}
/// <summary>
/// Port.
/// </summary>
int
Port
{
get
;
set
;
}
string
ToString
();
}
}
src/Titanium.Web.Proxy/Network/DebugCustomBufferedStream.cs
deleted
100644 → 0
View file @
d8df61ba
using
Titanium.Web.Proxy.StreamExtended.BufferPool
;
using
Titanium.Web.Proxy.StreamExtended.Network
;
#if DEBUG
using
System
;
using
System.IO
;
using
System.Text
;
using
System.Threading
;
namespace
Titanium.Web.Proxy.Network
{
internal
class
DebugCustomBufferedStream
:
CustomBufferedStream
{
private
const
string
basePath
=
@"."
;
private
static
int
counter
;
private
readonly
FileStream
fileStreamReceived
;
private
readonly
FileStream
fileStreamSent
;
public
DebugCustomBufferedStream
(
Guid
connectionId
,
string
type
,
Stream
baseStream
,
IBufferPool
bufferPool
,
bool
leaveOpen
=
false
)
:
base
(
baseStream
,
bufferPool
,
leaveOpen
)
{
Counter
=
Interlocked
.
Increment
(
ref
counter
);
fileStreamSent
=
new
FileStream
(
Path
.
Combine
(
basePath
,
$"
{
connectionId
}
_
{
type
}
_
{
Counter
}
_sent.dat"
),
FileMode
.
Create
);
fileStreamReceived
=
new
FileStream
(
Path
.
Combine
(
basePath
,
$"
{
connectionId
}
_
{
type
}
_
{
Counter
}
_received.dat"
),
FileMode
.
Create
);
}
public
int
Counter
{
get
;
}
protected
override
void
OnDataWrite
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
fileStreamSent
.
Write
(
buffer
,
offset
,
count
);
Flush
();
}
protected
override
void
OnDataRead
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
fileStreamReceived
.
Write
(
buffer
,
offset
,
count
);
Flush
();
}
public
void
LogException
(
Exception
ex
)
{
var
data
=
Encoding
.
UTF8
.
GetBytes
(
"EXCEPTION: "
+
ex
);
fileStreamReceived
.
Write
(
data
,
0
,
data
.
Length
);
fileStreamReceived
.
Flush
();
}
public
override
void
Flush
()
{
fileStreamSent
.
Flush
(
true
);
fileStreamReceived
.
Flush
(
true
);
if
(
CanWrite
)
{
base
.
Flush
();
}
}
protected
override
void
Dispose
(
bool
disposing
)
{
if
(
disposing
)
{
Flush
();
fileStreamSent
.
Dispose
();
fileStreamReceived
.
Dispose
();
}
base
.
Dispose
(
disposing
);
}
}
}
#endif
src/Titanium.Web.Proxy/Network/ProxyClient.cs
deleted
100644 → 0
View file @
d8df61ba
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Network.Tcp
;
using
Titanium.Web.Proxy.StreamExtended.Network
;
namespace
Titanium.Web.Proxy.Network
{
/// <summary>
/// This class wraps Tcp connection to client
/// </summary>
internal
class
ProxyClient
{
public
ProxyClient
(
TcpClientConnection
connection
,
CustomBufferedStream
clientStream
,
HttpResponseWriter
clientStreamWriter
)
{
Connection
=
connection
;
ClientStream
=
clientStream
;
ClientStreamWriter
=
clientStreamWriter
;
}
/// <summary>
/// TcpClient connection used to communicate with client
/// </summary>
internal
TcpClientConnection
Connection
{
get
;
}
/// <summary>
/// Holds the stream to client
/// </summary>
internal
CustomBufferedStream
ClientStream
{
get
;
}
/// <summary>
/// Used to write line by line to client
/// </summary>
internal
HttpResponseWriter
ClientStreamWriter
{
get
;
}
}
}
src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs
View file @
ebed40b1
...
...
@@ -86,7 +86,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
proxyServer
.
UpdateClientConnectionCount
(
false
);
tcpClient
.
CloseSocket
();
});
}
}
}
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
ebed40b1
...
...
@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal
string
GetConnectionCacheKey
(
string
remoteHostName
,
int
remotePort
,
bool
isHttps
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
IPEndPoint
?
upStreamEndPoint
,
ExternalProxy
?
externalProxy
)
IPEndPoint
?
upStreamEndPoint
,
I
ExternalProxy
?
externalProxy
)
{
// http version is ignored since its an application level decision b/w HTTP 1.0/1.1
// also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response.
...
...
@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
applicationProtocols
=
new
List
<
SslApplicationProtocol
>
{
applicationProtocol
};
}
ExternalProxy
?
customUpStreamProxy
=
null
;
I
ExternalProxy
?
customUpStreamProxy
=
null
;
bool
isHttps
=
session
.
IsHttps
;
if
(
server
.
GetCustomUpStreamProxyFunc
!=
null
)
...
...
@@ -170,7 +170,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal
async
Task
<
TcpServerConnection
>
GetServerConnection
(
ProxyServer
server
,
SessionEventArgsBase
session
,
bool
isConnect
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
noCache
,
CancellationToken
cancellationToken
)
{
ExternalProxy
?
customUpStreamProxy
=
null
;
I
ExternalProxy
?
customUpStreamProxy
=
null
;
bool
isHttps
=
session
.
IsHttps
;
if
(
server
.
GetCustomUpStreamProxyFunc
!=
null
)
...
...
@@ -208,10 +208,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <returns></returns>
internal
async
Task
<
TcpServerConnection
>
GetServerConnection
(
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
isConnect
,
ProxyServer
proxyServer
,
SessionEventArgsBase
?
session
,
IPEndPoint
?
upStreamEndPoint
,
ExternalProxy
?
externalProxy
,
ProxyServer
proxyServer
,
SessionEventArgsBase
?
session
,
IPEndPoint
?
upStreamEndPoint
,
I
ExternalProxy
?
externalProxy
,
bool
noCache
,
CancellationToken
cancellationToken
)
{
var
sslProtocol
=
session
?.
ProxyClient
.
Connection
.
SslProtocol
??
SslProtocols
.
None
;
var
sslProtocol
=
session
?.
Client
Connection
.
SslProtocol
??
SslProtocols
.
None
;
var
cacheKey
=
GetConnectionCacheKey
(
remoteHostName
,
remotePort
,
isHttps
,
applicationProtocols
,
upStreamEndPoint
,
externalProxy
);
...
...
@@ -262,7 +262,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <returns></returns>
private
async
Task
<
TcpServerConnection
>
createServerConnection
(
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
SslProtocols
sslProtocol
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
isConnect
,
ProxyServer
proxyServer
,
SessionEventArgsBase
?
session
,
IPEndPoint
?
upStreamEndPoint
,
ExternalProxy
?
externalProxy
,
string
cacheKey
,
ProxyServer
proxyServer
,
SessionEventArgsBase
?
session
,
IPEndPoint
?
upStreamEndPoint
,
I
ExternalProxy
?
externalProxy
,
string
cacheKey
,
CancellationToken
cancellationToken
)
{
// deny connection to proxy end points to avoid infinite connection loop.
...
...
@@ -297,14 +297,14 @@ namespace Titanium.Web.Proxy.Network.Tcp
}
TcpClient
?
tcpClient
=
null
;
CustomBuffered
Stream
?
stream
=
null
;
HttpServer
Stream
?
stream
=
null
;
SslApplicationProtocol
negotiatedApplicationProtocol
=
default
;
bool
retry
=
true
;
var
enabledSslProtocols
=
sslProtocol
;
retry
:
retry
:
try
{
string
hostname
=
useUpstreamProxy
?
externalProxy
!.
HostName
:
remoteHostName
;
...
...
@@ -323,6 +323,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
Array
.
Sort
(
ipAddresses
,
(
x
,
y
)
=>
x
.
AddressFamily
.
CompareTo
(
y
.
AddressFamily
));
Exception
lastException
=
null
;
for
(
int
i
=
0
;
i
<
ipAddresses
.
Length
;
i
++)
{
try
...
...
@@ -352,28 +353,29 @@ namespace Titanium.Web.Proxy.Network.Tcp
}
catch
(
Exception
e
)
{
if
(
i
==
ipAddresses
.
Length
-
1
)
{
throw
new
Exception
(
$"Could not establish connection to
{
hostname
}
"
,
e
);
}
// dispose the current TcpClient and try the next address
lastException
=
e
;
tcpClient
?.
Dispose
();
tcpClient
=
null
;
}
}
if
(
tcpClient
==
null
)
{
throw
new
Exception
(
$"Could not establish connection to
{
hostname
}
"
,
lastException
);
}
if
(
session
!=
null
)
{
session
.
TimeLine
[
"Connection Established"
]
=
DateTime
.
Now
;
}
await
proxyServer
.
InvokeConnectionCreateEvent
(
tcpClient
!
,
false
);
await
proxyServer
.
InvokeConnectionCreateEvent
(
tcpClient
,
false
);
stream
=
new
CustomBufferedStream
(
tcpClient
!
.
GetStream
(),
proxyServer
.
BufferPool
);
stream
=
new
HttpServerStream
(
tcpClient
.
GetStream
(),
proxyServer
.
BufferPool
);
if
(
useUpstreamProxy
&&
(
isConnect
||
isHttps
))
{
var
writer
=
new
HttpRequestWriter
(
stream
,
proxyServer
.
BufferPool
);
string
authority
=
$"
{
remoteHostName
}
:
{
remotePort
}
"
;
var
connectRequest
=
new
ConnectRequest
(
authority
)
{
...
...
@@ -391,7 +393,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
HttpHeader
.
GetProxyAuthorizationHeader
(
externalProxy
.
UserName
,
externalProxy
.
Password
));
}
await
writer
.
WriteRequestAsync
(
connectRequest
,
cancellationToken
:
cancellationToken
);
await
stream
.
WriteRequestAsync
(
connectRequest
,
cancellationToken
:
cancellationToken
);
string
httpStatus
=
await
stream
.
ReadLineAsync
(
cancellationToken
)
??
throw
new
ServerConnectionException
(
"Server connection was closed."
);
...
...
@@ -411,7 +413,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
var
sslStream
=
new
SslStream
(
stream
,
false
,
proxyServer
.
ValidateServerCertificate
,
proxyServer
.
SelectClientCertificate
);
stream
=
new
CustomBuffered
Stream
(
sslStream
,
proxyServer
.
BufferPool
);
stream
=
new
HttpServer
Stream
(
sslStream
,
proxyServer
.
BufferPool
);
var
options
=
new
SslClientAuthenticationOptions
{
...
...
@@ -430,11 +432,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
session
.
TimeLine
[
"HTTPS Established"
]
=
DateTime
.
Now
;
}
}
}
catch
(
IOException
ex
)
when
(
ex
.
HResult
==
unchecked
((
int
)
0x80131620
)
&&
retry
&&
enabledSslProtocols
>=
SslProtocols
.
Tls11
)
{
stream
?.
Dispose
();
tcpClient
?.
Close
();
enabledSslProtocols
=
SslProtocols
.
Tls
;
retry
=
false
;
goto
retry
;
...
...
src/Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
View file @
ebed40b1
...
...
@@ -15,15 +15,14 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
internal
class
TcpServerConnection
:
IDisposable
{
internal
TcpServerConnection
(
ProxyServer
proxyServer
,
TcpClient
tcpClient
,
CustomBuffered
Stream
stream
,
internal
TcpServerConnection
(
ProxyServer
proxyServer
,
TcpClient
tcpClient
,
HttpServer
Stream
stream
,
string
hostName
,
int
port
,
bool
isHttps
,
SslApplicationProtocol
negotiatedApplicationProtocol
,
Version
version
,
bool
useUpstreamProxy
,
ExternalProxy
?
upStreamProxy
,
IPEndPoint
?
upStreamEndPoint
,
string
cacheKey
)
Version
version
,
bool
useUpstreamProxy
,
I
ExternalProxy
?
upStreamProxy
,
IPEndPoint
?
upStreamEndPoint
,
string
cacheKey
)
{
this
.
t
cpClient
=
tcpClient
;
T
cpClient
=
tcpClient
;
LastAccess
=
DateTime
.
Now
;
this
.
proxyServer
=
proxyServer
;
this
.
proxyServer
.
UpdateServerConnectionCount
(
true
);
StreamWriter
=
new
HttpRequestWriter
(
stream
,
proxyServer
.
BufferPool
);
Stream
=
stream
;
HostName
=
hostName
;
Port
=
port
;
...
...
@@ -41,7 +40,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal
bool
IsClosed
=>
Stream
.
IsClosed
;
internal
ExternalProxy
?
UpStreamProxy
{
get
;
set
;
}
internal
I
ExternalProxy
?
UpStreamProxy
{
get
;
set
;
}
internal
string
HostName
{
get
;
set
;
}
...
...
@@ -63,22 +62,15 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
internal
Version
Version
{
get
;
set
;
}
=
HttpHeader
.
VersionUnknown
;
private
readonly
TcpClient
tcpClient
;
/// <summary>
/// The TcpClient.
/// </summary>
internal
TcpClient
TcpClient
=>
tcpClient
;
internal
TcpClient
TcpClient
{
get
;
}
/// <summary>
/// Used to write lines to server
/// </summary>
internal
HttpRequestWriter
StreamWriter
{
get
;
}
/// <summary>
/// Server stream
/// </summary>
internal
CustomBufferedStream
Stream
{
get
;
}
internal
HttpServerStream
Stream
{
get
;
}
/// <summary>
/// Last time this connection was used
...
...
@@ -107,8 +99,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
// This way we can push tcp Time_Wait to server side when possible.
await
Task
.
Delay
(
1000
);
proxyServer
.
UpdateServerConnectionCount
(
false
);
Stream
?
.
Dispose
();
t
cpClient
.
CloseSocket
();
Stream
.
Dispose
();
T
cpClient
.
CloseSocket
();
});
}
...
...
src/Titanium.Web.Proxy/ProxyServer.cs
View file @
ebed40b1
...
...
@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy
/// </summary>
private
WinHttpWebProxyFinder
?
systemProxyResolver
;
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of ProxyServer class with provided parameters.
...
...
@@ -145,7 +145,7 @@ namespace Titanium.Web.Proxy
/// Defaults to false.
/// </summary>
public
bool
EnableWinAuth
{
get
;
set
;
}
/// <summary>
/// Enable disable HTTP/2 support.
/// Warning: HTTP/2 support is very limited
...
...
@@ -253,12 +253,12 @@ namespace Titanium.Web.Proxy
/// <summary>
/// External proxy used for Http requests.
/// </summary>
public
ExternalProxy
?
UpStreamHttpProxy
{
get
;
set
;
}
public
I
ExternalProxy
?
UpStreamHttpProxy
{
get
;
set
;
}
/// <summary>
/// External proxy used for Https requests.
/// </summary>
public
ExternalProxy
?
UpStreamHttpsProxy
{
get
;
set
;
}
public
I
ExternalProxy
?
UpStreamHttpsProxy
{
get
;
set
;
}
/// <summary>
/// Local adapter/NIC endpoint where proxy makes request via.
...
...
@@ -275,7 +275,7 @@ namespace Titanium.Web.Proxy
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests.
/// User should return the ExternalProxy object with valid credentials.
/// </summary>
public
Func
<
SessionEventArgsBase
,
Task
<
ExternalProxy
?>>?
GetCustomUpStreamProxyFunc
{
get
;
set
;
}
public
Func
<
SessionEventArgsBase
,
Task
<
I
ExternalProxy
?>>?
GetCustomUpStreamProxyFunc
{
get
;
set
;
}
/// <summary>
/// Callback for error events in this proxy instance.
...
...
@@ -709,7 +709,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="sessionEventArgs">The session.</param>
/// <returns>The external proxy as task result.</returns>
private
Task
<
ExternalProxy
?>
getSystemUpStreamProxy
(
SessionEventArgsBase
sessionEventArgs
)
private
Task
<
I
ExternalProxy
?>
getSystemUpStreamProxy
(
SessionEventArgsBase
sessionEventArgs
)
{
var
proxy
=
systemProxyResolver
!.
GetProxy
(
sessionEventArgs
.
HttpClient
.
Request
.
RequestUri
);
return
Task
.
FromResult
(
proxy
);
...
...
@@ -803,15 +803,8 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="clientStream">The client stream.</param>
/// <param name="exception">The exception.</param>
private
void
onException
(
CustomBuffered
Stream
clientStream
,
Exception
exception
)
private
void
onException
(
HttpClient
Stream
clientStream
,
Exception
exception
)
{
#if DEBUG
if
(
clientStream
is
DebugCustomBufferedStream
debugStream
)
{
debugStream
.
LogException
(
exception
);
}
#endif
ExceptionFunc
(
exception
);
}
...
...
src/Titanium.Web.Proxy/RequestHandler.cs
View file @
ebed40b1
...
...
@@ -31,13 +31,11 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint">The proxy endpoint.</param>
/// <param name="clientConnection">The client connection.</param>
/// <param name="clientStream">The client stream.</param>
/// <param name="clientStreamWriter">The client stream writer.</param>
/// <param name="cancellationTokenSource">The cancellation token source for this async task.</param>
/// <param name="connectArgs">The Connect request if this is a HTTPS request from explicit endpoint.</param>
/// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param>
private
async
Task
handleHttpSessionRequest
(
ProxyEndPoint
endPoint
,
TcpClientConnection
clientConnection
,
CustomBufferedStream
clientStream
,
HttpResponseWriter
clientStreamWriter
,
CancellationTokenSource
cancellationTokenSource
,
TunnelConnectSessionEventArgs
?
connectArgs
=
null
,
HttpClientStream
clientStream
,
CancellationTokenSource
cancellationTokenSource
,
TunnelConnectSessionEventArgs
?
connectArgs
=
null
,
Task
<
TcpServerConnection
>?
prefetchConnectionTask
=
null
)
{
var
connectRequest
=
connectArgs
?.
HttpClient
.
ConnectRequest
;
...
...
@@ -66,7 +64,7 @@ namespace Titanium.Web.Proxy
return
;
}
var
args
=
new
SessionEventArgs
(
this
,
endPoint
,
new
ProxyClient
(
clientConnection
,
clientStream
,
clientStreamWriter
)
,
connectRequest
,
cancellationTokenSource
)
var
args
=
new
SessionEventArgs
(
this
,
endPoint
,
clientConnection
,
clientStream
,
connectRequest
,
cancellationTokenSource
)
{
UserData
=
connectArgs
?.
UserData
};
...
...
@@ -101,7 +99,7 @@ namespace Titanium.Web.Proxy
await
onBeforeResponse
(
args
);
// send the response
await
clientStream
Writer
.
WriteResponseAsync
(
args
.
HttpClient
.
Response
,
await
clientStream
.
WriteResponseAsync
(
args
.
HttpClient
.
Response
,
cancellationToken
:
cancellationToken
);
return
;
}
...
...
@@ -276,7 +274,7 @@ namespace Titanium.Web.Proxy
// if upgrading to websocket then relay the request without reading the contents
await
handleWebSocketUpgrade
(
requestHttpMethod
,
requestHttpUrl
,
requestVersion
,
args
,
args
.
HttpClient
.
Request
,
args
.
HttpClient
.
Response
,
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
HttpClient
.
Response
,
args
.
ClientStream
,
connection
,
cancellationTokenSource
,
cancellationToken
);
return
false
;
}
...
...
@@ -304,13 +302,13 @@ namespace Titanium.Web.Proxy
// If a successful 100 continue request was made, inform that to the client and reset response
if
(
request
.
ExpectationSucceeded
)
{
var
clientStreamWriter
=
args
.
ProxyClient
.
ClientStreamWriter
;
var
writer
=
args
.
ClientStream
;
var
response
=
args
.
HttpClient
.
Response
;
var
headerBuilder
=
new
HeaderBuilder
();
headerBuilder
.
WriteResponseLine
(
response
.
HttpVersion
,
response
.
StatusCode
,
response
.
StatusDescription
);
headerBuilder
.
WriteHeaders
(
response
.
Headers
);
await
clientStreamW
riter
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
await
w
riter
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
await
args
.
ClearResponse
(
cancellationToken
);
}
...
...
@@ -320,14 +318,12 @@ namespace Titanium.Web.Proxy
{
if
(
request
.
IsBodyRead
)
{
var
writer
=
args
.
HttpClient
.
Connection
.
StreamWriter
;
await
writer
.
WriteBodyAsync
(
body
!,
request
.
IsChunked
,
cancellationToken
);
await
args
.
HttpClient
.
Connection
.
Stream
.
WriteBodyAsync
(
body
!,
request
.
IsChunked
,
cancellationToken
);
}
else
if
(!
request
.
ExpectationFailed
)
{
// get the request body unless an unsuccessful 100 continue request was made
HttpWriter
writer
=
args
.
HttpClient
.
Connection
.
StreamWriter
!;
await
args
.
CopyRequestBodyAsync
(
writer
,
TransformationMode
.
None
,
cancellationToken
);
await
args
.
CopyRequestBodyAsync
(
args
.
HttpClient
.
Connection
.
Stream
,
TransformationMode
.
None
,
cancellationToken
);
}
}
...
...
@@ -357,7 +353,7 @@ namespace Titanium.Web.Proxy
supportedAcceptEncoding
.
Add
(
"identity"
);
requestHeaders
.
SetOrAddHeaderValue
(
KnownHeaders
.
AcceptEncoding
,
string
.
Join
(
","
,
supportedAcceptEncoding
));
string
.
Join
(
",
"
,
supportedAcceptEncoding
));
}
requestHeaders
.
FixProxyHeaders
();
...
...
src/Titanium.Web.Proxy/ResponseHandler.cs
View file @
ebed40b1
...
...
@@ -64,13 +64,13 @@ namespace Titanium.Web.Proxy
// it may changed in the user event
response
=
args
.
HttpClient
.
Response
;
var
clientStream
Writer
=
args
.
ProxyClient
.
ClientStreamWriter
;
var
clientStream
=
args
.
ClientStream
;
// user set custom response by ignoring original response from server.
if
(
response
.
Locked
)
{
// write custom user response with body and return.
await
clientStream
Writer
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
await
clientStream
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
if
(
args
.
HttpClient
.
HasConnection
&&
!
args
.
HttpClient
.
CloseServerConnection
)
{
...
...
@@ -108,7 +108,7 @@ namespace Titanium.Web.Proxy
if
(
response
.
IsBodyRead
)
{
await
clientStream
Writer
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
await
clientStream
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
}
else
{
...
...
@@ -116,12 +116,12 @@ namespace Titanium.Web.Proxy
var
headerBuilder
=
new
HeaderBuilder
();
headerBuilder
.
WriteResponseLine
(
response
.
HttpVersion
,
response
.
StatusCode
,
response
.
StatusDescription
);
headerBuilder
.
WriteHeaders
(
response
.
Headers
);
await
clientStream
Writer
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
await
clientStream
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
// Write body if exists
if
(
response
.
HasBody
)
{
await
args
.
CopyResponseBodyAsync
(
clientStream
Writer
,
TransformationMode
.
None
,
await
args
.
CopyResponseBodyAsync
(
clientStream
,
TransformationMode
.
None
,
cancellationToken
);
}
}
...
...
src/Titanium.Web.Proxy/StreamExtended/Network/CopyStream.cs
View file @
ebed40b1
using
System
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.StreamExtended.BufferPool
;
namespace
Titanium.Web.Proxy.StreamExtended.Network
...
...
@@ -11,9 +12,9 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary>
internal
class
CopyStream
:
ILineStream
,
IDisposable
{
private
readonly
CustomBufferedStream
reader
;
private
readonly
IHttpStreamReader
reader
;
private
readonly
I
Custom
StreamWriter
writer
;
private
readonly
I
Http
StreamWriter
writer
;
private
readonly
IBufferPool
bufferPool
;
...
...
@@ -27,7 +28,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
public
long
ReadBytes
{
get
;
private
set
;
}
public
CopyStream
(
CustomBufferedStream
reader
,
ICustom
StreamWriter
writer
,
IBufferPool
bufferPool
)
public
CopyStream
(
IHttpStreamReader
reader
,
IHttp
StreamWriter
writer
,
IBufferPool
bufferPool
)
{
this
.
reader
=
reader
;
this
.
writer
=
writer
;
...
...
@@ -61,7 +62,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
public
ValueTask
<
string
?>
ReadLineAsync
(
CancellationToken
cancellationToken
=
default
)
{
return
CustomBuffered
Stream
.
ReadLineInternalAsync
(
this
,
bufferPool
,
cancellationToken
);
return
Http
Stream
.
ReadLineInternalAsync
(
this
,
bufferPool
,
cancellationToken
);
}
public
void
Dispose
()
...
...
src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamReader.cs
0 → 100644
View file @
ebed40b1
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.StreamExtended.Network
{
public
interface
IHttpStreamReader
:
ILineStream
{
int
Read
(
byte
[]
buffer
,
int
offset
,
int
count
);
Task
<
int
>
ReadAsync
(
byte
[]
buffer
,
int
offset
,
int
count
,
CancellationToken
cancellationToken
);
}
}
src/Titanium.Web.Proxy/StreamExtended/Network/I
Custom
StreamWriter.cs
→
src/Titanium.Web.Proxy/StreamExtended/Network/I
Http
StreamWriter.cs
View file @
ebed40b1
using
System.Threading
;
using
System
;
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.StreamExtended.Network
...
...
@@ -6,10 +7,13 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <summary>
/// A concrete implementation of this interface is required when calling CopyStream.
/// </summary>
public
interface
ICustom
StreamWriter
internal
interface
IHttp
StreamWriter
{
void
Write
(
byte
[]
buffer
,
int
i
,
int
bufferLength
);
Task
WriteAsync
(
byte
[]
buffer
,
int
i
,
int
bufferLength
,
CancellationToken
cancellationToken
);
Task
CopyBodyAsync
(
IHttpStreamReader
streamReader
,
bool
isChunked
,
long
contentLength
,
Action
<
byte
[],
int
,
int
>?
onCopy
,
CancellationToken
cancellationToken
);
}
}
\ No newline at end of file
}
src/Titanium.Web.Proxy/StreamExtended/Network/PeekStreamReader.cs
View file @
ebed40b1
...
...
@@ -53,5 +53,5 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
return
buffer
;
}
}
}
}
src/Titanium.Web.Proxy/StreamExtended/SslTools.cs
View file @
ebed40b1
using
System.Collections.Generic
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.StreamExtended.BufferPool
;
using
Titanium.Web.Proxy.StreamExtended.Models
;
using
Titanium.Web.Proxy.StreamExtended.Network
;
...
...
@@ -19,7 +20,7 @@ namespace Titanium.Web.Proxy.StreamExtended
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public
static
async
Task
<
ClientHelloInfo
?>
PeekClientHello
(
CustomBuffered
Stream
clientStream
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
public
static
async
Task
<
ClientHelloInfo
?>
PeekClientHello
(
IPeek
Stream
clientStream
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
{
// detects the HTTPS ClientHello message as it is described in the following url:
// https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
...
...
@@ -127,11 +128,10 @@ namespace Titanium.Web.Proxy.StreamExtended
return
null
;
}
byte
[]
ciphersData
=
peekStream
.
ReadBytes
(
length
);
int
[]
ciphers
=
new
int
[
ciphersData
.
Length
/
2
];
int
[]
ciphers
=
new
int
[
length
/
2
];
for
(
int
i
=
0
;
i
<
ciphers
.
Length
;
i
++)
{
ciphers
[
i
]
=
(
ciphersData
[
2
*
i
]
<<
8
)
+
ciphersData
[
2
*
i
+
1
]
;
ciphers
[
i
]
=
peekStream
.
ReadInt16
()
;
}
length
=
peekStream
.
ReadByte
();
...
...
@@ -178,7 +178,7 @@ namespace Titanium.Web.Proxy.StreamExtended
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public
static
async
Task
<
bool
>
IsServerHello
(
CustomBuffered
Stream
stream
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
)
public
static
async
Task
<
bool
>
IsServerHello
(
IPeek
Stream
stream
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
)
{
var
serverHello
=
await
PeekServerHello
(
stream
,
bufferPool
,
cancellationToken
);
return
serverHello
!=
null
;
...
...
@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.StreamExtended
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public
static
async
Task
<
ServerHelloInfo
?>
PeekServerHello
(
CustomBuffered
Stream
serverStream
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
public
static
async
Task
<
ServerHelloInfo
?>
PeekServerHello
(
IPeek
Stream
serverStream
,
IBufferPool
bufferPool
,
CancellationToken
cancellationToken
=
default
)
{
// detects the HTTPS ClientHello message as it is described in the following url:
// https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
...
...
@@ -286,11 +286,11 @@ namespace Titanium.Web.Proxy.StreamExtended
int
cipherSuite
=
peekStream
.
ReadInt16
();
byte
compressionMethod
=
peekStream
.
ReadByte
();
int
extens
t
ionsStartPosition
=
peekStream
.
Position
;
int
extensionsStartPosition
=
peekStream
.
Position
;
Dictionary
<
string
,
SslExtension
>?
extensions
=
null
;
if
(
extens
t
ionsStartPosition
<
recordLength
+
5
)
if
(
extensionsStartPosition
<
recordLength
+
5
)
{
extensions
=
await
ReadExtensions
(
majorVersion
,
minorVersion
,
peekStream
,
bufferPool
,
cancellationToken
);
}
...
...
@@ -298,7 +298,7 @@ namespace Titanium.Web.Proxy.StreamExtended
var
serverHelloInfo
=
new
ServerHelloInfo
(
3
,
majorVersion
,
minorVersion
,
random
,
sessionId
,
cipherSuite
,
peekStream
.
Position
)
{
CompressionMethod
=
compressionMethod
,
EntensionsStartPosition
=
extens
t
ionsStartPosition
,
EntensionsStartPosition
=
extensionsStartPosition
,
Extensions
=
extensions
,
};
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.Mono.csproj
View file @
ebed40b1
...
...
@@ -13,7 +13,7 @@
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5
.2
" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
View file @
ebed40b1
...
...
@@ -13,7 +13,7 @@
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5
.2
" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
ebed40b1
...
...
@@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5
.2
" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.3" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.3" />
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
View file @
ebed40b1
...
...
@@ -15,7 +15,7 @@
<tags></tags>
<dependencies>
<group
targetFramework=
"netstandard2.0"
>
<dependency
id=
"Portable.BouncyCastle"
version=
"1.8.5"
/>
<dependency
id=
"Portable.BouncyCastle"
version=
"1.8.5
.2
"
/>
<dependency
id=
"BrotliSharpLib"
version=
"0.3.3"
/>
<dependency
id=
"Microsoft.Win32.Registry"
version=
"4.6.0"
/>
<dependency
id=
"System.Buffers"
version=
"4.5.0"
/>
...
...
@@ -24,7 +24,7 @@
<dependency
id=
"System.Security.Principal.Windows"
version=
"4.6.0"
/>
</group>
<group
targetFramework=
"netstandard2.1"
>
<dependency
id=
"Portable.BouncyCastle"
version=
"1.8.5"
/>
<dependency
id=
"Portable.BouncyCastle"
version=
"1.8.5
.2
"
/>
<dependency
id=
"BrotliSharpLib"
version=
"0.3.3"
/>
<dependency
id=
"Microsoft.Win32.Registry"
version=
"4.6.0"
/>
<dependency
id=
"System.Buffers"
version=
"4.5.0"
/>
...
...
src/Titanium.Web.Proxy/TransparentClientHandler.cs
View file @
ebed40b1
...
...
@@ -33,8 +33,7 @@ namespace Titanium.Web.Proxy
var
cancellationTokenSource
=
new
CancellationTokenSource
();
var
cancellationToken
=
cancellationTokenSource
.
Token
;
var
clientStream
=
new
CustomBufferedStream
(
clientConnection
.
GetStream
(),
BufferPool
);
var
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferPool
);
var
clientStream
=
new
HttpClientStream
(
clientConnection
.
GetStream
(),
BufferPool
);
SslStream
?
sslStream
=
null
;
...
...
@@ -75,14 +74,12 @@ namespace Titanium.Web.Proxy
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
// HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferPool
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferPool
);
clientStream
=
new
HttpClientStream
(
sslStream
,
BufferPool
);
}
catch
(
Exception
e
)
{
var
certname
=
certificate
?.
GetNameInfo
(
X509NameType
.
SimpleName
,
false
);
var
session
=
new
SessionEventArgs
(
this
,
endPoint
,
new
ProxyClient
(
clientConnection
,
clientStream
,
clientStreamWriter
)
,
null
,
var
session
=
new
SessionEventArgs
(
this
,
endPoint
,
clientConnection
,
clientStream
,
null
,
cancellationTokenSource
);
throw
new
ProxyConnectException
(
$"Couldn't authenticate host '
{
httpsHostName
}
' with certificate '
{
certname
}
'."
,
e
,
session
);
...
...
@@ -108,7 +105,7 @@ namespace Titanium.Web.Proxy
{
// clientStream.Available should be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
,
cancellationToken
);
await
connection
.
Stream
Writer
.
WriteAsync
(
data
,
0
,
available
,
true
,
cancellationToken
);
await
connection
.
Stream
.
WriteAsync
(
data
,
0
,
available
,
true
,
cancellationToken
);
}
finally
{
...
...
@@ -133,7 +130,7 @@ namespace Titanium.Web.Proxy
// HTTPS server created - we can now decrypt the client's traffic
// Now create the request
await
handleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
c
lientStreamWriter
,
c
ancellationTokenSource
);
await
handleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
cancellationTokenSource
);
}
catch
(
ProxyException
e
)
{
...
...
@@ -155,11 +152,6 @@ namespace Titanium.Web.Proxy
{
sslStream
?.
Dispose
();
clientStream
.
Dispose
();
if
(!
cancellationTokenSource
.
IsCancellationRequested
)
{
cancellationTokenSource
.
Cancel
();
}
}
}
}
...
...
src/Titanium.Web.Proxy/WebSocketHandler.cs
View file @
ebed40b1
...
...
@@ -18,15 +18,14 @@ namespace Titanium.Web.Proxy
/// </summary>
private
async
Task
handleWebSocketUpgrade
(
string
requestHttpMethod
,
string
requestHttpUrl
,
Version
requestVersion
,
SessionEventArgs
args
,
Request
request
,
Response
response
,
CustomBufferedStream
clientStream
,
HttpResponseWriter
clientStreamWriter
,
TcpServerConnection
serverConnection
,
HttpClientStream
clientStream
,
TcpServerConnection
serverConnection
,
CancellationTokenSource
cancellationTokenSource
,
CancellationToken
cancellationToken
)
{
// prepare the prefix content
var
headerBuilder
=
new
HeaderBuilder
();
headerBuilder
.
WriteRequestLine
(
requestHttpMethod
,
requestHttpUrl
,
requestVersion
);
headerBuilder
.
WriteHeaders
(
request
.
Headers
);
await
serverConnection
.
Stream
Writer
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
await
serverConnection
.
Stream
.
WriteHeadersAsync
(
headerBuilder
,
cancellationToken
);
string
httpStatus
;
try
...
...
@@ -51,7 +50,7 @@ namespace Titanium.Web.Proxy
if
(!
args
.
IsTransparent
)
{
await
clientStream
Writer
.
WriteResponseAsync
(
response
,
await
clientStream
.
WriteResponseAsync
(
response
,
cancellationToken
:
cancellationToken
);
}
...
...
src/Titanium.Web.Proxy/WinAuthHandler.cs
View file @
ebed40b1
...
...
@@ -175,7 +175,7 @@ namespace Titanium.Web.Proxy
// Add custom div to body to clarify that the proxy (not the client browser) failed authentication
string
authErrorMessage
=
"<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy ("
+
args
.
ProxyClient
.
Connection
.
LocalEndPoint
+
args
.
Client
Connection
.
LocalEndPoint
+
") failed. Please check credentials.</h2></div>"
;
string
originalErrorMessage
=
"<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>"
;
...
...
tests/Titanium.Web.Proxy.IntegrationTests/NestedProxyTests.cs
View file @
ebed40b1
...
...
@@ -69,7 +69,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
};
var
client
=
testSuite
.
GetClient
(
proxy1
,
true
);
var
response
=
await
client
.
PostAsync
(
new
Uri
(
server
.
ListeningHttpsUrl
),
new
StringContent
(
"hello server. I am a client."
));
...
...
tests/Titanium.Web.Proxy.IntegrationTests/Titanium.Web.Proxy.IntegrationTests.csproj
View file @
ebed40b1
...
...
@@ -17,7 +17,7 @@
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.
3
.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.
4
.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
</ItemGroup>
...
...
tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj
View file @
ebed40b1
...
...
@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.
3
.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.
4
.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
</ItemGroup>
...
...
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