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
60feeb00
Commit
60feeb00
authored
Apr 26, 2019
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
http/2: using some default settings from specification, process the settings frame
process the rst_stream frame
parent
66c41133
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
81 additions
and
9 deletions
+81
-9
Http2Helper.cs
src/Titanium.Web.Proxy/Http2/Http2Helper.cs
+81
-9
No files found.
src/Titanium.Web.Proxy/Http2/Http2Helper.cs
View file @
60feeb00
...
@@ -39,14 +39,19 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -39,14 +39,19 @@ namespace Titanium.Web.Proxy.Http2
CancellationTokenSource
cancellationTokenSource
,
Guid
connectionId
,
CancellationTokenSource
cancellationTokenSource
,
Guid
connectionId
,
ExceptionHandler
exceptionFunc
)
ExceptionHandler
exceptionFunc
)
{
{
var
clientSettings
=
new
Http2Settings
();
var
serverSettings
=
new
Http2Settings
();
;
var
sessions
=
new
ConcurrentDictionary
<
int
,
SessionEventArgs
>();
var
sessions
=
new
ConcurrentDictionary
<
int
,
SessionEventArgs
>();
// Now async relay all server=>client & client=>server data
// Now async relay all server=>client & client=>server data
var
sendRelay
=
var
sendRelay
=
copyHttp2FrameAsync
(
clientStream
,
serverStream
,
onDataSend
,
sessionFactory
,
sessions
,
onBeforeRequest
,
copyHttp2FrameAsync
(
clientStream
,
serverStream
,
onDataSend
,
clientSettings
,
serverSettings
,
sessionFactory
,
sessions
,
onBeforeRequest
,
bufferSize
,
connectionId
,
true
,
cancellationTokenSource
.
Token
,
exceptionFunc
);
bufferSize
,
connectionId
,
true
,
cancellationTokenSource
.
Token
,
exceptionFunc
);
var
receiveRelay
=
var
receiveRelay
=
copyHttp2FrameAsync
(
serverStream
,
clientStream
,
onDataReceive
,
sessionFactory
,
sessions
,
onBeforeResponse
,
copyHttp2FrameAsync
(
serverStream
,
clientStream
,
onDataReceive
,
serverSettings
,
clientSettings
,
sessionFactory
,
sessions
,
onBeforeResponse
,
bufferSize
,
connectionId
,
false
,
cancellationTokenSource
.
Token
,
exceptionFunc
);
bufferSize
,
connectionId
,
false
,
cancellationTokenSource
.
Token
,
exceptionFunc
);
await
Task
.
WhenAny
(
sendRelay
,
receiveRelay
);
await
Task
.
WhenAny
(
sendRelay
,
receiveRelay
);
...
@@ -56,15 +61,17 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -56,15 +61,17 @@ namespace Titanium.Web.Proxy.Http2
}
}
private
static
async
Task
copyHttp2FrameAsync
(
Stream
input
,
Stream
output
,
Action
<
byte
[],
int
,
int
>
onCopy
,
private
static
async
Task
copyHttp2FrameAsync
(
Stream
input
,
Stream
output
,
Action
<
byte
[],
int
,
int
>
onCopy
,
Http2Settings
localSettings
,
Http2Settings
remoteSettings
,
Func
<
SessionEventArgs
>
sessionFactory
,
ConcurrentDictionary
<
int
,
SessionEventArgs
>
sessions
,
Func
<
SessionEventArgs
>
sessionFactory
,
ConcurrentDictionary
<
int
,
SessionEventArgs
>
sessions
,
Func
<
SessionEventArgs
,
Task
>
onBeforeRequestResponse
,
Func
<
SessionEventArgs
,
Task
>
onBeforeRequestResponse
,
int
bufferSize
,
Guid
connectionId
,
bool
isClient
,
CancellationToken
cancellationToken
,
int
bufferSize
,
Guid
connectionId
,
bool
isClient
,
CancellationToken
cancellationToken
,
ExceptionHandler
exceptionFunc
)
ExceptionHandler
exceptionFunc
)
{
{
var
decoder
=
new
Decoder
(
8192
,
4096
*
16
);
int
headerTableSize
=
0
;
Decoder
decoder
=
null
;
var
headerBuffer
=
new
byte
[
9
];
var
headerBuffer
=
new
byte
[
9
];
var
buffer
=
new
byte
[
32768
]
;
byte
[]
buffer
=
null
;
while
(
true
)
while
(
true
)
{
{
int
read
=
await
forceRead
(
input
,
headerBuffer
,
0
,
9
,
cancellationToken
);
int
read
=
await
forceRead
(
input
,
headerBuffer
,
0
,
9
,
cancellationToken
);
...
@@ -80,6 +87,11 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -80,6 +87,11 @@ namespace Titanium.Web.Proxy.Http2
int
streamId
=
((
headerBuffer
[
5
]
&
0x7f
)
<<
24
)
+
(
headerBuffer
[
6
]
<<
16
)
+
(
headerBuffer
[
7
]
<<
8
)
+
int
streamId
=
((
headerBuffer
[
5
]
&
0x7f
)
<<
24
)
+
(
headerBuffer
[
6
]
<<
16
)
+
(
headerBuffer
[
7
]
<<
8
)
+
headerBuffer
[
8
];
headerBuffer
[
8
];
if
(
buffer
==
null
||
buffer
.
Length
<
localSettings
.
MaxFrameSize
)
{
buffer
=
new
byte
[
localSettings
.
MaxFrameSize
];
}
read
=
await
forceRead
(
input
,
buffer
,
0
,
length
,
cancellationToken
);
read
=
await
forceRead
(
input
,
buffer
,
0
,
length
,
cancellationToken
);
onCopy
(
buffer
,
0
,
read
);
onCopy
(
buffer
,
0
,
read
);
if
(
read
!=
length
)
if
(
read
!=
length
)
...
@@ -145,7 +157,7 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -145,7 +157,7 @@ namespace Titanium.Web.Proxy.Http2
}
}
}
}
}
}
else
if
(
type
==
1
/*
headers
*/
)
else
if
(
type
==
1
/*
headers
*/
)
{
{
bool
endHeaders
=
(
flags
&
(
int
)
Http2FrameFlag
.
EndHeaders
)
!=
0
;
bool
endHeaders
=
(
flags
&
(
int
)
Http2FrameFlag
.
EndHeaders
)
!=
0
;
bool
padded
=
(
flags
&
(
int
)
Http2FrameFlag
.
Padded
)
!=
0
;
bool
padded
=
(
flags
&
(
int
)
Http2FrameFlag
.
Padded
)
!=
0
;
...
@@ -181,13 +193,18 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -181,13 +193,18 @@ namespace Titanium.Web.Proxy.Http2
});
});
try
try
{
{
lock
(
decoder
)
// recreate the decoder when new value is bigger
// should we recreate when smaller, too?
if
(
decoder
==
null
||
headerTableSize
<
localSettings
.
HeaderTableSize
)
{
{
decoder
.
Decode
(
new
BinaryReader
(
new
MemoryStream
(
buffer
,
offset
,
dataLength
)),
headerTableSize
=
localSettings
.
HeaderTableSize
;
headerListener
);
decoder
=
new
Decoder
(
8192
,
headerTableSize
);
decoder
.
EndHeaderBlock
();
}
}
decoder
.
Decode
(
new
BinaryReader
(
new
MemoryStream
(
buffer
,
offset
,
dataLength
)),
headerListener
);
decoder
.
EndHeaderBlock
();
if
(
isClient
)
if
(
isClient
)
{
{
var
request
=
args
.
HttpClient
.
Request
;
var
request
=
args
.
HttpClient
.
Request
;
...
@@ -225,6 +242,53 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -225,6 +242,53 @@ namespace Titanium.Web.Proxy.Http2
rr
.
Locked
=
true
;
rr
.
Locked
=
true
;
}
}
}
}
else
if
(
type
==
4
/* settings */
)
{
if
(
length
%
6
!=
0
)
{
// https://httpwg.org/specs/rfc7540.html#SETTINGS
// 6.5. SETTINGS
// A SETTINGS frame with a length other than a multiple of 6 octets MUST be treated as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR
throw
new
ProxyHttpException
(
"Invalid settings length"
,
null
,
null
);
}
int
pos
=
0
;
while
(
pos
<
length
)
{
int
identifier
=
(
buffer
[
pos
++]
<<
8
)
+
buffer
[
pos
++];
int
value
=
(
buffer
[
pos
++]
<<
24
)
+
(
buffer
[
pos
++]
<<
16
)
+
(
buffer
[
pos
++]
<<
8
)
+
buffer
[
pos
++];
if
(
identifier
==
1
/*SETTINGS_HEADER_TABLE_SIZE*/
)
{
//System.Diagnostics.Debug.WriteLine("HEADER SIZE CONN: " + connectionId + ", CLIENT: " + isClient + ", value: " + value);
remoteSettings
.
HeaderTableSize
=
value
;
}
else
if
(
identifier
==
5
/*SETTINGS_MAX_FRAME_SIZE*/
)
{
remoteSettings
.
MaxFrameSize
=
value
;
}
}
}
if
(
type
==
3
/* rst_stream */
)
{
int
errorCode
=
(
buffer
[
0
]
<<
24
)
+
(
buffer
[
1
]
<<
16
)
+
(
buffer
[
2
]
<<
8
)
+
buffer
[
3
];
if
(
streamId
==
0
)
{
// connection error
exceptionFunc
(
new
ProxyHttpException
(
"HTTP/2 connection error. Error code: "
+
errorCode
,
null
,
args
));
return
;
}
else
{
// stream error
sessions
.
TryRemove
(
streamId
,
out
_
);
if
(
errorCode
!=
8
/*cancel*/
)
{
exceptionFunc
(
new
ProxyHttpException
(
"HTTP/2 stream error. Error code: "
+
errorCode
,
null
,
args
));
}
}
}
if
(!
isClient
&&
endStream
)
if
(!
isClient
&&
endStream
)
{
{
...
@@ -269,6 +333,14 @@ namespace Titanium.Web.Proxy.Http2
...
@@ -269,6 +333,14 @@ namespace Titanium.Web.Proxy.Http2
return
totalRead
;
return
totalRead
;
}
}
class
Http2Settings
{
public
int
HeaderTableSize
{
get
;
set
;
}
=
4096
;
public
int
MaxFrameSize
{
get
;
set
;
}
=
16384
;
}
class
MyHeaderListener
:
IHeaderListener
class
MyHeaderListener
:
IHeaderListener
{
{
private
readonly
Action
<
string
,
string
>
addHeaderFunc
;
private
readonly
Action
<
string
,
string
>
addHeaderFunc
;
...
...
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