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
d90adbb1
Commit
d90adbb1
authored
Jul 21, 2019
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
various fixes
parent
17a4efec
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
272 additions
and
66 deletions
+272
-66
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+4
-4
MainWindow.xaml
examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml
+1
-0
MainWindow.xaml.cs
examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
+38
-6
ExplicitClientHandler.cs
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
+8
-5
TcpConnectionFactory.cs
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+2
-2
ProxyServer.cs
src/Titanium.Web.Proxy/ProxyServer.cs
+15
-1
RequestHandler.cs
src/Titanium.Web.Proxy/RequestHandler.cs
+10
-5
DefaultBufferPool.cs
....Web.Proxy/StreamExtended/BufferPool/DefaultBufferPool.cs
+4
-14
IBufferPool.cs
...tanium.Web.Proxy/StreamExtended/BufferPool/IBufferPool.cs
+1
-0
CustomBufferedStream.cs
....Web.Proxy/StreamExtended/Network/CustomBufferedStream.cs
+120
-23
TaskResult.cs
src/Titanium.Web.Proxy/StreamExtended/Network/TaskResult.cs
+58
-0
Titanium.Web.Proxy.Mono.csproj
src/Titanium.Web.Proxy/Titanium.Web.Proxy.Mono.csproj
+1
-0
Titanium.Web.Proxy.NetCore.csproj
src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
+1
-0
Titanium.Web.Proxy.csproj
src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
+1
-0
Titanium.Web.Proxy.nuspec
src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
+2
-0
TransparentClientHandler.cs
src/Titanium.Web.Proxy/TransparentClientHandler.cs
+6
-6
No files found.
examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
d90adbb1
...
...
@@ -119,7 +119,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
private
async
Task
onBeforeTunnelConnectRequest
(
object
sender
,
TunnelConnectSessionEventArgs
e
)
{
string
hostname
=
e
.
HttpClient
.
Request
.
RequestUri
.
Host
;
await
writeToConsole
(
"Tunnel to: "
+
hostname
);
//
await writeToConsole("Tunnel to: " + hostname);
if
(
hostname
.
Contains
(
"dropbox.com"
))
{
...
...
@@ -138,8 +138,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
// intecept & cancel redirect or update requests
private
async
Task
onRequest
(
object
sender
,
SessionEventArgs
e
)
{
await
writeToConsole
(
"Active Client Connections:"
+
((
ProxyServer
)
sender
).
ClientConnectionCount
);
await
writeToConsole
(
e
.
HttpClient
.
Request
.
Url
);
//
await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
//
await writeToConsole(e.HttpClient.Request.Url);
// store it in the UserData property
// It can be a simple integer, Guid, or any type
...
...
@@ -189,7 +189,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
private
async
Task
onResponse
(
object
sender
,
SessionEventArgs
e
)
{
await
writeToConsole
(
"Active Server Connections:"
+
((
ProxyServer
)
sender
).
ServerConnectionCount
);
//
await writeToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);
string
ext
=
System
.
IO
.
Path
.
GetExtension
(
e
.
HttpClient
.
Request
.
RequestUri
.
AbsolutePath
);
...
...
examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml
View file @
d90adbb1
...
...
@@ -54,6 +54,7 @@
</TabItem>
</TabControl>
<StackPanel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="3" Orientation="Horizontal">
<ToggleButton IsChecked="True" Content="On/Off" Click="ButtonProxyOnOff_OnClick" />
<TextBlock Text="ClientConnectionCount:" />
<TextBlock Text="{Binding ClientConnectionCount}" Margin="10,0,20,0" />
<TextBlock Text="ServerConnectionCount:" />
...
...
examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
View file @
d90adbb1
...
...
@@ -8,6 +8,7 @@ using System.Text;
using
System.Threading.Tasks
;
using
System.Windows
;
using
System.Windows.Controls
;
using
System.Windows.Controls.Primitives
;
using
System.Windows.Input
;
using
System.Windows.Media.Imaging
;
using
Titanium.Web.Proxy.EventArguments
;
...
...
@@ -284,15 +285,26 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
if
(
e
.
Key
==
Key
.
Delete
)
{
bool
isSelected
=
false
;
var
selectedItems
=
((
ListView
)
sender
).
SelectedItems
;
Sessions
.
SuppressNotification
=
true
;
foreach
(
var
item
in
selectedItems
.
Cast
<
SessionListItem
>().
ToArray
())
{
if
(
item
==
SelectedSession
)
{
isSelected
=
true
;
}
Sessions
.
Remove
(
item
);
sessionDictionary
.
Remove
(
item
.
HttpClient
);
}
Sessions
.
SuppressNotification
=
false
;
if
(
isSelected
)
{
SelectedSession
=
null
;
}
}
}
...
...
@@ -300,6 +312,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
if
(
SelectedSession
==
null
)
{
TextBoxRequest
.
Text
=
null
;
TextBoxResponse
.
Text
=
string
.
Empty
;
ImageResponse
.
Source
=
null
;
return
;
}
...
...
@@ -307,7 +322,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
var
session
=
SelectedSession
.
HttpClient
;
var
request
=
session
.
Request
;
var
fullData
=
(
request
.
IsBodyRead
?
request
.
Body
:
null
)
??
new
byte
[
0
]
;
var
fullData
=
(
request
.
IsBodyRead
?
request
.
Body
:
null
)
??
Array
.
Empty
<
byte
>()
;
var
data
=
fullData
;
bool
truncated
=
data
.
Length
>
truncateLimit
;
if
(
truncated
)
...
...
@@ -324,7 +339,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
TextBoxRequest
.
Text
=
sb
.
ToString
();
var
response
=
session
.
Response
;
fullData
=
(
response
.
IsBodyRead
?
response
.
Body
:
null
)
??
new
byte
[
0
]
;
fullData
=
(
response
.
IsBodyRead
?
response
.
Body
:
null
)
??
Array
.
Empty
<
byte
>()
;
data
=
fullData
;
truncated
=
data
.
Length
>
truncateLimit
;
if
(
truncated
)
...
...
@@ -348,16 +363,33 @@ namespace Titanium.Web.Proxy.Examples.Wpf
try
{
using
(
MemoryStream
stream
=
new
MemoryStream
(
fullData
))
if
(
fullData
.
Length
>
0
)
{
using
(
var
stream
=
new
MemoryStream
(
fullData
))
{
ImageResponse
.
Source
=
BitmapFrame
.
Create
(
stream
,
BitmapCreateOptions
.
None
,
BitmapCacheOption
.
OnLoad
);
}
}
}
catch
{
ImageResponse
.
Source
=
null
;
}
}
private
void
ButtonProxyOnOff_OnClick
(
object
sender
,
RoutedEventArgs
e
)
{
var
button
=
(
ToggleButton
)
sender
;
if
(
button
.
IsChecked
==
true
)
{
proxyServer
.
SetAsSystemProxy
((
ExplicitProxyEndPoint
)
proxyServer
.
ProxyEndPoints
[
0
],
ProxyProtocolType
.
AllHttp
);
}
else
{
proxyServer
.
RestoreOriginalProxySettings
();
}
}
}
}
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
View file @
d90adbb1
...
...
@@ -265,8 +265,8 @@ namespace Titanium.Web.Proxy
try
{
await
clientStream
.
ReadAsync
(
data
,
0
,
available
,
cancellationToken
);
// clientStream.Available should be at most BufferSize because it is using the same buffer size
await
clientStream
.
ReadAsync
(
data
,
0
,
available
,
cancellationToken
);
await
connection
.
StreamWriter
.
WriteAsync
(
data
,
0
,
available
,
true
,
cancellationToken
);
}
finally
...
...
@@ -279,11 +279,14 @@ namespace Titanium.Web.Proxy
((
ConnectResponse
)
connectArgs
.
HttpClient
.
Response
).
ServerHelloInfo
=
serverHelloInfo
;
}
if
(!
clientStream
.
IsClosed
&&
!
connection
.
Stream
.
IsClosed
)
{
await
TcpHelper
.
SendRaw
(
clientStream
,
connection
.
Stream
,
BufferPool
,
BufferSize
,
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataSent
(
buffer
,
offset
,
count
);
},
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataReceived
(
buffer
,
offset
,
count
);
},
connectArgs
.
CancellationTokenSource
,
ExceptionFunc
);
}
}
finally
{
await
tcpConnectionFactory
.
Release
(
connection
,
true
);
...
...
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
d90adbb1
...
...
@@ -481,6 +481,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
try
{
var
cutOff
=
DateTime
.
Now
.
AddSeconds
(-
1
*
Server
.
ConnectionTimeOutSeconds
);
foreach
(
var
item
in
cache
)
{
var
queue
=
item
.
Value
;
...
...
@@ -489,7 +490,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
if
(
queue
.
TryDequeue
(
out
var
connection
))
{
var
cutOff
=
DateTime
.
Now
.
AddSeconds
(-
1
*
Server
.
ConnectionTimeOutSeconds
);
if
(!
Server
.
EnableConnectionPool
||
connection
.
LastAccess
<
cutOff
)
{
...
...
@@ -512,7 +512,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
var
emptyKeys
=
cache
.
Where
(
x
=>
x
.
Value
.
Count
==
0
).
Select
(
x
=>
x
.
Key
).
ToList
();
foreach
(
string
key
in
emptyKeys
)
{
cache
.
TryRemove
(
key
,
out
var
_
);
cache
.
TryRemove
(
key
,
out
_
);
}
}
finally
...
...
src/Titanium.Web.Proxy/ProxyServer.cs
View file @
d90adbb1
...
...
@@ -516,6 +516,20 @@ namespace Titanium.Web.Proxy
DisableSystemProxy
(
ProxyProtocolType
.
Https
);
}
/// <summary>
/// Restores the original proxy settings.
/// </summary>
public
void
RestoreOriginalProxySettings
()
{
if
(!
RunTime
.
IsWindows
)
{
throw
new
NotSupportedException
(
@"Setting system proxy settings are only supported in Windows.
Please manually configure your operating system to use this proxy's port and address."
);
}
systemProxySettingsManager
.
RestoreOriginalSettings
();
}
/// <summary>
/// Clear the specified proxy setting for current machine.
/// </summary>
...
...
@@ -524,7 +538,7 @@ namespace Titanium.Web.Proxy
if
(!
RunTime
.
IsWindows
)
{
throw
new
NotSupportedException
(
@"Setting system proxy settings are only supported in Windows.
Please manually conf
ugure you
operating system to use this proxy's port and address."
);
Please manually conf
igure your
operating system to use this proxy's port and address."
);
}
systemProxySettingsManager
.
RemoveProxy
(
protocolType
);
...
...
src/Titanium.Web.Proxy/RequestHandler.cs
View file @
d90adbb1
...
...
@@ -65,6 +65,11 @@ namespace Titanium.Web.Proxy
// (assuming HTTP connection is kept alive by client)
while
(
true
)
{
if
(
clientStream
.
IsClosed
)
{
return
;
}
// read the request line
string
httpCmd
=
await
clientStream
.
ReadLineAsync
(
cancellationToken
);
...
...
@@ -255,11 +260,11 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
"Session was terminated by user."
);
}
//Release server connection for each HTTP session instead of per client connection.
//This will be more efficient especially when client is idly holding server connection
//between sessions without using it.
//Do not release authenticated connections for performance reasons.
//Otherwise it will keep authenticating per session.
//
Release server connection for each HTTP session instead of per client connection.
//
This will be more efficient especially when client is idly holding server connection
//
between sessions without using it.
//
Do not release authenticated connections for performance reasons.
//
Otherwise it will keep authenticating per session.
if
(
EnableConnectionPool
&&
connection
!=
null
&&
!
connection
.
IsWinAuthenticated
)
{
...
...
src/Titanium.Web.Proxy/StreamExtended/BufferPool/DefaultBufferPool.cs
View file @
d90adbb1
using
System.Collections.Concurrent
;
using
System.Buffers
;
using
System.Collections.Concurrent
;
namespace
Titanium.Web.Proxy.StreamExtended.BufferPool
{
...
...
@@ -10,8 +11,6 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool
/// </summary>
public
class
DefaultBufferPool
:
IBufferPool
{
private
readonly
ConcurrentStack
<
byte
[
]>
buffers
=
new
ConcurrentStack
<
byte
[
]>
();
/// <summary>
/// Gets a buffer.
/// </summary>
...
...
@@ -19,12 +18,7 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool
/// <returns></returns>
public
byte
[]
GetBuffer
(
int
bufferSize
)
{
if
(!
buffers
.
TryPop
(
out
var
buffer
)
||
buffer
.
Length
!=
bufferSize
)
{
buffer
=
new
byte
[
bufferSize
];
}
return
buffer
;
return
ArrayPool
<
byte
>.
Shared
.
Rent
(
bufferSize
);
}
/// <summary>
...
...
@@ -33,15 +27,11 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool
/// <param name="buffer">The buffer.</param>
public
void
ReturnBuffer
(
byte
[]
buffer
)
{
if
(
buffer
!=
null
)
{
buffers
.
Push
(
buffer
);
}
ArrayPool
<
byte
>.
Shared
.
Return
(
buffer
);
}
public
void
Dispose
()
{
buffers
.
Clear
();
}
}
}
src/Titanium.Web.Proxy/StreamExtended/BufferPool/IBufferPool.cs
View file @
d90adbb1
...
...
@@ -9,6 +9,7 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool
public
interface
IBufferPool
:
IDisposable
{
byte
[]
GetBuffer
(
int
bufferSize
);
void
ReturnBuffer
(
byte
[]
buffer
);
}
}
src/Titanium.Web.Proxy/StreamExtended/Network/CustomBufferedStream.cs
View file @
d90adbb1
...
...
@@ -17,13 +17,14 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <seealso cref="System.IO.Stream" />
public
class
CustomBufferedStream
:
Stream
,
ICustomStreamReader
{
private
readonly
Stream
baseStream
;
private
readonly
bool
leaveOpen
;
private
byte
[]
streamBuffer
;
// default to UTF-8
private
static
readonly
Encoding
encoding
=
Encoding
.
UTF8
;
private
static
bool
networkStreamHack
=
true
;
private
int
bufferLength
;
private
int
bufferPos
;
...
...
@@ -40,8 +41,28 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
public
event
EventHandler
<
DataEventArgs
>
DataWrite
;
public
Stream
BaseStream
{
get
;
}
public
bool
IsClosed
=>
closed
;
static
CustomBufferedStream
()
{
// TODO: remove this hack when removing .NET 4.x support
try
{
var
method
=
typeof
(
NetworkStream
).
GetMethod
(
nameof
(
Stream
.
ReadAsync
),
new
Type
[]
{
typeof
(
byte
[]),
typeof
(
int
),
typeof
(
int
),
typeof
(
CancellationToken
)
});
if
(
method
!=
null
&&
method
.
DeclaringType
!=
typeof
(
Stream
))
{
networkStreamHack
=
false
;
}
}
catch
{
// ignore
}
}
/// <summary>
/// Initializes a new instance of the <see cref="CustomBufferedStream"/> class.
/// </summary>
...
...
@@ -51,7 +72,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <param name="leaveOpen"><see langword="true" /> to leave the stream open after disposing the <see cref="T:CustomBufferedStream" /> object; otherwise, <see langword="false" />.</param>
public
CustomBufferedStream
(
Stream
baseStream
,
IBufferPool
bufferPool
,
int
bufferSize
,
bool
leaveOpen
=
false
)
{
this
.
b
aseStream
=
baseStream
;
B
aseStream
=
baseStream
;
BufferSize
=
bufferSize
;
this
.
leaveOpen
=
leaveOpen
;
streamBuffer
=
bufferPool
.
GetBuffer
(
bufferSize
);
...
...
@@ -63,7 +84,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary>
public
override
void
Flush
()
{
b
aseStream
.
Flush
();
B
aseStream
.
Flush
();
}
/// <summary>
...
...
@@ -78,7 +99,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
{
bufferLength
=
0
;
bufferPos
=
0
;
return
b
aseStream
.
Seek
(
offset
,
origin
);
return
B
aseStream
.
Seek
(
offset
,
origin
);
}
/// <summary>
...
...
@@ -87,7 +108,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <param name="value">The desired length of the current stream in bytes.</param>
public
override
void
SetLength
(
long
value
)
{
b
aseStream
.
SetLength
(
value
);
B
aseStream
.
SetLength
(
value
);
}
/// <summary>
...
...
@@ -127,7 +148,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
public
override
void
Write
(
byte
[]
buffer
,
int
offset
,
int
count
)
{
OnDataWrite
(
buffer
,
offset
,
count
);
b
aseStream
.
Write
(
buffer
,
offset
,
count
);
B
aseStream
.
Write
(
buffer
,
offset
,
count
);
}
/// <summary>
...
...
@@ -160,7 +181,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </returns>
public
override
Task
FlushAsync
(
CancellationToken
cancellationToken
=
default
)
{
return
b
aseStream
.
FlushAsync
(
cancellationToken
);
return
B
aseStream
.
FlushAsync
(
cancellationToken
);
}
/// <summary>
...
...
@@ -329,7 +350,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
{
OnDataWrite
(
buffer
,
offset
,
count
);
await
b
aseStream
.
WriteAsync
(
buffer
,
offset
,
count
,
cancellationToken
);
await
B
aseStream
.
WriteAsync
(
buffer
,
offset
,
count
,
cancellationToken
);
}
/// <summary>
...
...
@@ -343,7 +364,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
{
buffer
[
0
]
=
value
;
OnDataWrite
(
buffer
,
0
,
1
);
b
aseStream
.
Write
(
buffer
,
0
,
1
);
B
aseStream
.
Write
(
buffer
,
0
,
1
);
}
finally
{
...
...
@@ -373,7 +394,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
closed
=
true
;
if
(!
leaveOpen
)
{
b
aseStream
.
Dispose
();
B
aseStream
.
Dispose
();
}
var
buffer
=
streamBuffer
;
...
...
@@ -385,27 +406,27 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <summary>
/// When overridden in a derived class, gets a value indicating whether the current stream supports reading.
/// </summary>
public
override
bool
CanRead
=>
b
aseStream
.
CanRead
;
public
override
bool
CanRead
=>
B
aseStream
.
CanRead
;
/// <summary>
/// When overridden in a derived class, gets a value indicating whether the current stream supports seeking.
/// </summary>
public
override
bool
CanSeek
=>
b
aseStream
.
CanSeek
;
public
override
bool
CanSeek
=>
B
aseStream
.
CanSeek
;
/// <summary>
/// When overridden in a derived class, gets a value indicating whether the current stream supports writing.
/// </summary>
public
override
bool
CanWrite
=>
b
aseStream
.
CanWrite
;
public
override
bool
CanWrite
=>
B
aseStream
.
CanWrite
;
/// <summary>
/// Gets a value that determines whether the current stream can time out.
/// </summary>
public
override
bool
CanTimeout
=>
b
aseStream
.
CanTimeout
;
public
override
bool
CanTimeout
=>
B
aseStream
.
CanTimeout
;
/// <summary>
/// When overridden in a derived class, gets the length in bytes of the stream.
/// </summary>
public
override
long
Length
=>
b
aseStream
.
Length
;
public
override
long
Length
=>
B
aseStream
.
Length
;
/// <summary>
/// Gets a value indicating whether data is available.
...
...
@@ -422,8 +443,8 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary>
public
override
long
Position
{
get
=>
b
aseStream
.
Position
;
set
=>
b
aseStream
.
Position
=
value
;
get
=>
B
aseStream
.
Position
;
set
=>
B
aseStream
.
Position
=
value
;
}
/// <summary>
...
...
@@ -431,8 +452,8 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary>
public
override
int
ReadTimeout
{
get
=>
b
aseStream
.
ReadTimeout
;
set
=>
b
aseStream
.
ReadTimeout
=
value
;
get
=>
B
aseStream
.
ReadTimeout
;
set
=>
B
aseStream
.
ReadTimeout
=
value
;
}
/// <summary>
...
...
@@ -440,8 +461,8 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary>
public
override
int
WriteTimeout
{
get
=>
b
aseStream
.
WriteTimeout
;
set
=>
b
aseStream
.
WriteTimeout
=
value
;
get
=>
B
aseStream
.
WriteTimeout
;
set
=>
B
aseStream
.
WriteTimeout
=
value
;
}
/// <summary>
...
...
@@ -466,7 +487,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
bool
result
=
false
;
try
{
int
readBytes
=
b
aseStream
.
Read
(
streamBuffer
,
bufferLength
,
streamBuffer
.
Length
-
bufferLength
);
int
readBytes
=
B
aseStream
.
Read
(
streamBuffer
,
bufferLength
,
streamBuffer
.
Length
-
bufferLength
);
result
=
readBytes
>
0
;
if
(
result
)
{
...
...
@@ -516,7 +537,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
bool
result
=
false
;
try
{
int
readBytes
=
await
b
aseStream
.
ReadAsync
(
streamBuffer
,
bufferLength
,
bytesToRead
,
cancellationToken
);
int
readBytes
=
await
B
aseStream
.
ReadAsync
(
streamBuffer
,
bufferLength
,
bytesToRead
,
cancellationToken
);
result
=
readBytes
>
0
;
if
(
result
)
{
...
...
@@ -622,5 +643,81 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
Buffer
.
BlockCopy
(
buffer
,
0
,
newBuffer
,
0
,
buffer
.
Length
);
buffer
=
newBuffer
;
}
/// <summary>
/// Base Stream.BeginRead will call this.Read and block thread (we don't want this, Network stream handles async)
/// In order to really async Reading Launch this.ReadAsync as Task will fire NetworkStream.ReadAsync
/// See Threads here :
/// https://github.com/justcoding121/Stream-Extended/pull/43
/// https://github.com/justcoding121/Titanium-Web-Proxy/issues/575
/// </summary>
/// <returns></returns>
public
override
IAsyncResult
BeginRead
(
byte
[]
buffer
,
int
offset
,
int
count
,
AsyncCallback
callback
,
object
state
)
{
if
(!
networkStreamHack
)
{
return
base
.
BeginRead
(
buffer
,
offset
,
count
,
callback
,
state
);
}
var
vAsyncResult
=
this
.
ReadAsync
(
buffer
,
offset
,
count
);
vAsyncResult
.
ContinueWith
(
pAsyncResult
=>
{
//use TaskExtended to pass State as AsyncObject
//callback will call EndRead (otherwise, it will block)
callback
?.
Invoke
(
new
TaskResult
<
int
>(
pAsyncResult
,
state
));
});
return
vAsyncResult
;
}
/// <summary>
/// override EndRead to handle async Reading (see BeginRead comment)
/// </summary>
/// <returns></returns>
public
override
int
EndRead
(
IAsyncResult
asyncResult
)
{
if
(!
networkStreamHack
)
{
return
base
.
EndRead
(
asyncResult
);
}
return
((
TaskResult
<
int
>)
asyncResult
).
Result
;
}
/// <summary>
/// Fix the .net bug with SslStream slow WriteAsync
/// https://github.com/justcoding121/Titanium-Web-Proxy/issues/495
/// Stream.BeginWrite + Stream.BeginRead uses the same SemaphoreSlim(1)
/// That's why we need to call NetworkStream.BeginWrite only (while read is waiting SemaphoreSlim)
/// </summary>
/// <returns></returns>
public
override
IAsyncResult
BeginWrite
(
byte
[]
buffer
,
int
offset
,
int
count
,
AsyncCallback
callback
,
object
state
)
{
if
(!
networkStreamHack
)
{
return
base
.
BeginWrite
(
buffer
,
offset
,
count
,
callback
,
state
);
}
var
vAsyncResult
=
this
.
WriteAsync
(
buffer
,
offset
,
count
);
vAsyncResult
.
ContinueWith
(
pAsyncResult
=>
{
callback
?.
Invoke
(
new
TaskResult
(
pAsyncResult
,
state
));
});
return
vAsyncResult
;
}
public
override
void
EndWrite
(
IAsyncResult
asyncResult
)
{
if
(!
networkStreamHack
)
{
base
.
EndWrite
(
asyncResult
);
return
;
}
((
TaskResult
)
asyncResult
).
GetResult
();
}
}
}
src/Titanium.Web.Proxy/StreamExtended/Network/TaskResult.cs
0 → 100644
View file @
d90adbb1
using
System
;
using
System.Threading
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// Mimic a Task but you can set AsyncState
/// </summary>
/// <typeparam name="T"></typeparam>
public
class
TaskResult
:
IAsyncResult
{
Task
Task
;
readonly
object
asyncState
;
public
TaskResult
(
Task
pTask
,
object
state
)
{
Task
=
pTask
;
asyncState
=
state
;
}
public
object
AsyncState
=>
asyncState
;
public
WaitHandle
AsyncWaitHandle
=>
((
IAsyncResult
)
Task
).
AsyncWaitHandle
;
public
bool
CompletedSynchronously
=>
((
IAsyncResult
)
Task
).
CompletedSynchronously
;
public
bool
IsCompleted
=>
Task
.
IsCompleted
;
public
void
GetResult
()
{
this
.
Task
.
GetAwaiter
().
GetResult
();
}
}
/// <summary>
/// Mimic a Task<T> but you can set AsyncState
/// </summary>
/// <typeparam name="T"></typeparam>
public
class
TaskResult
<
T
>
:
IAsyncResult
{
Task
<
T
>
Task
;
readonly
object
asyncState
;
public
TaskResult
(
Task
<
T
>
pTask
,
object
state
)
{
Task
=
pTask
;
asyncState
=
state
;
}
public
object
AsyncState
=>
asyncState
;
public
WaitHandle
AsyncWaitHandle
=>
((
IAsyncResult
)
Task
).
AsyncWaitHandle
;
public
bool
CompletedSynchronously
=>
((
IAsyncResult
)
Task
).
CompletedSynchronously
;
public
bool
IsCompleted
=>
Task
.
IsCompleted
;
public
T
Result
=>
Task
.
Result
;
}
}
src/Titanium.Web.Proxy/Titanium.Web.Proxy.Mono.csproj
View file @
d90adbb1
...
...
@@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.NetCore.csproj
View file @
d90adbb1
...
...
@@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.csproj
View file @
d90adbb1
...
...
@@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
...
...
src/Titanium.Web.Proxy/Titanium.Web.Proxy.nuspec
View file @
d90adbb1
...
...
@@ -18,12 +18,14 @@
<dependency
id=
"Portable.BouncyCastle"
version=
"1.8.5"
/>
<dependency
id=
"BrotliSharpLib"
version=
"0.3.3"
/>
<dependency
id=
"Microsoft.Win32.Registry"
version=
"4.5.0"
/>
<dependency
id=
"System.Buffers"
version=
"4.5.0"
/>
<dependency
id=
"System.Security.Principal.Windows"
version=
"4.5.1"
/>
</group>
<group
targetFramework=
"netcoreapp2.1"
>
<dependency
id=
"Portable.BouncyCastle"
version=
"1.8.5"
/>
<dependency
id=
"BrotliSharpLib"
version=
"0.3.3"
/>
<dependency
id=
"Microsoft.Win32.Registry"
version=
"4.5.0"
/>
<dependency
id=
"System.Buffers"
version=
"4.5.0"
/>
<dependency
id=
"System.Security.Principal.Windows"
version=
"4.5.1"
/>
</group>
</dependencies>
...
...
src/Titanium.Web.Proxy/TransparentClientHandler.cs
View file @
d90adbb1
...
...
@@ -103,7 +103,6 @@ namespace Titanium.Web.Proxy
try
{
CustomBufferedStream
serverStream
=
null
;
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
...
...
@@ -114,9 +113,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
);
serverStream
=
connection
.
Stream
;
await
serverStream
.
WriteAsync
(
data
,
0
,
available
,
cancellationToken
);
await
serverStream
.
FlushAsync
(
cancellationToken
);
await
connection
.
StreamWriter
.
WriteAsync
(
data
,
0
,
available
,
true
,
cancellationToken
);
}
finally
{
...
...
@@ -124,9 +121,12 @@ namespace Titanium.Web.Proxy
}
}
await
TcpHelper
.
SendRaw
(
clientStream
,
serverStream
,
BufferPool
,
BufferSize
,
if
(!
clientStream
.
IsClosed
&&
!
connection
.
Stream
.
IsClosed
)
{
await
TcpHelper
.
SendRaw
(
clientStream
,
connection
.
Stream
,
BufferPool
,
BufferSize
,
null
,
null
,
cancellationTokenSource
,
ExceptionFunc
);
}
}
finally
{
await
tcpConnectionFactory
.
Release
(
connection
,
true
);
...
...
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