Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
8994b65a
Commit
8994b65a
authored
Sep 21, 2018
by
gejun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move parsing/serialization of H2Settings into http2_rpc_protocol.cpp
parent
664467d1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
128 additions
and
199 deletions
+128
-199
http2.cpp
src/brpc/http2.cpp
+9
-153
http2.h
src/brpc/http2.h
+4
-27
http2_rpc_protocol.cpp
src/brpc/policy/http2_rpc_protocol.cpp
+115
-19
No files found.
src/brpc/http2.cpp
View file @
8994b65a
...
...
@@ -19,167 +19,24 @@
namespace
brpc
{
enum
H2SettingsIdentifier
{
HTTP2_SETTINGS_HEADER_TABLE_SIZE
=
0x1
,
HTTP2_SETTINGS_ENABLE_PUSH
=
0x2
,
HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
=
0x3
,
HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
=
0x4
,
HTTP2_SETTINGS_MAX_FRAME_SIZE
=
0x5
,
HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
=
0x6
};
inline
uint16_t
LoadUint16
(
butil
::
IOBufBytesIterator
&
it
)
{
uint16_t
v
=
*
it
;
++
it
;
v
=
((
v
<<
8
)
|
*
it
);
++
it
;
return
v
;
}
inline
uint32_t
LoadUint32
(
butil
::
IOBufBytesIterator
&
it
)
{
uint32_t
v
=
*
it
;
++
it
;
v
=
((
v
<<
8
)
|
*
it
);
++
it
;
v
=
((
v
<<
8
)
|
*
it
);
++
it
;
v
=
((
v
<<
8
)
|
*
it
);
++
it
;
return
v
;
}
inline
void
SaveUint16
(
void
*
out
,
uint16_t
v
)
{
uint8_t
*
p
=
(
uint8_t
*
)
out
;
p
[
0
]
=
(
v
>>
8
)
&
0xFF
;
p
[
1
]
=
v
&
0xFF
;
}
inline
void
SaveUint32
(
void
*
out
,
uint32_t
v
)
{
uint8_t
*
p
=
(
uint8_t
*
)
out
;
p
[
0
]
=
(
v
>>
24
)
&
0xFF
;
p
[
1
]
=
(
v
>>
16
)
&
0xFF
;
p
[
2
]
=
(
v
>>
8
)
&
0xFF
;
p
[
3
]
=
v
&
0xFF
;
}
H2Settings
::
H2Settings
()
:
header_table_size
(
DEFAULT_HEADER_TABLE_SIZE
)
,
enable_push
(
DEFAULT_ENABLE_PUSH
)
,
enable_push
(
false
)
,
max_concurrent_streams
(
std
::
numeric_limits
<
uint32_t
>::
max
())
,
initial_window_size
(
DEFAULT_INITIAL_WINDOW_SIZE
)
,
max_frame_size
(
DEFAULT_MAX_FRAME_SIZE
)
,
max_header_list_size
(
std
::
numeric_limits
<
uint32_t
>::
max
())
{
}
bool
H2Settings
::
ParseFrom
(
butil
::
IOBufBytesIterator
&
it
,
size_t
n
)
{
const
uint32_t
npairs
=
n
/
6
;
if
(
npairs
*
6
!=
n
)
{
LOG
(
ERROR
)
<<
"Invalid payload_size="
<<
n
;
return
false
;
}
for
(
uint32_t
i
=
0
;
i
<
npairs
;
++
i
)
{
uint16_t
id
=
LoadUint16
(
it
);
uint32_t
value
=
LoadUint32
(
it
);
switch
(
static_cast
<
H2SettingsIdentifier
>
(
id
))
{
case
HTTP2_SETTINGS_HEADER_TABLE_SIZE
:
header_table_size
=
value
;
break
;
case
HTTP2_SETTINGS_ENABLE_PUSH
:
if
(
value
>
1
)
{
LOG
(
ERROR
)
<<
"Invalid value="
<<
value
<<
" for ENABLE_PUSH"
;
return
false
;
}
enable_push
=
value
;
break
;
case
HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
:
max_concurrent_streams
=
value
;
break
;
case
HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
:
if
(
value
>
MAX_INITIAL_WINDOW_SIZE
)
{
LOG
(
ERROR
)
<<
"Invalid initial_window_size="
<<
value
;
return
false
;
}
initial_window_size
=
value
;
break
;
case
HTTP2_SETTINGS_MAX_FRAME_SIZE
:
if
(
value
>
MAX_OF_MAX_FRAME_SIZE
||
value
<
DEFAULT_MAX_FRAME_SIZE
)
{
LOG
(
ERROR
)
<<
"Invalid max_frame_size="
<<
value
;
return
false
;
}
max_frame_size
=
value
;
break
;
case
HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
:
max_header_list_size
=
value
;
break
;
default
:
// An endpoint that receives a SETTINGS frame with any unknown or
// unsupported identifier MUST ignore that setting (section 6.5.2)
LOG
(
WARNING
)
<<
"Unknown setting, id="
<<
id
<<
" value="
<<
value
;
break
;
}
}
return
true
;
}
size_t
H2Settings
::
ByteSize
()
const
{
size_t
size
=
0
;
if
(
header_table_size
!=
DEFAULT_HEADER_TABLE_SIZE
)
{
size
+=
6
;
}
if
(
enable_push
!=
DEFAULT_ENABLE_PUSH
)
{
size
+=
6
;
}
if
(
max_concurrent_streams
!=
std
::
numeric_limits
<
uint32_t
>::
max
())
{
size
+=
6
;
}
if
(
initial_window_size
!=
DEFAULT_INITIAL_WINDOW_SIZE
)
{
size
+=
6
;
}
if
(
max_frame_size
!=
DEFAULT_MAX_FRAME_SIZE
)
{
size
+=
6
;
}
if
(
max_header_list_size
!=
std
::
numeric_limits
<
uint32_t
>::
max
())
{
size
+=
6
;
}
return
size
;
}
size_t
H2Settings
::
SerializeTo
(
void
*
out
)
const
{
uint8_t
*
p
=
(
uint8_t
*
)
out
;
if
(
header_table_size
!=
DEFAULT_HEADER_TABLE_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_HEADER_TABLE_SIZE
);
SaveUint32
(
p
+
2
,
header_table_size
);
p
+=
6
;
}
if
(
enable_push
!=
DEFAULT_ENABLE_PUSH
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_ENABLE_PUSH
);
SaveUint32
(
p
+
2
,
enable_push
);
p
+=
6
;
}
if
(
max_concurrent_streams
!=
std
::
numeric_limits
<
uint32_t
>::
max
())
{
SaveUint16
(
p
,
HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
);
SaveUint32
(
p
+
2
,
max_concurrent_streams
);
p
+=
6
;
}
if
(
initial_window_size
!=
DEFAULT_INITIAL_WINDOW_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
);
SaveUint32
(
p
+
2
,
initial_window_size
);
p
+=
6
;
}
if
(
max_frame_size
!=
DEFAULT_MAX_FRAME_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_MAX_FRAME_SIZE
);
SaveUint32
(
p
+
2
,
max_frame_size
);
p
+=
6
;
}
if
(
max_header_list_size
!=
std
::
numeric_limits
<
uint32_t
>::
max
())
{
SaveUint16
(
p
,
HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
);
SaveUint32
(
p
+
2
,
max_header_list_size
);
p
+=
6
;
}
return
static_cast
<
size_t
>
(
p
-
(
uint8_t
*
)
out
);
}
void
H2Settings
::
Print
(
std
::
ostream
&
os
)
const
{
os
<<
"{header_table_size="
<<
header_table_size
<<
" enable_push="
<<
enable_push
<<
" max_concurrent_streams="
<<
max_concurrent_streams
<<
" initial_window_size="
<<
initial_window_size
<<
" max_frame_size="
<<
max_frame_size
<<
" max_header_list_size="
<<
max_header_list_size
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
H2Settings
&
s
)
{
os
<<
"{header_table_size="
<<
s
.
header_table_size
<<
" enable_push="
<<
s
.
enable_push
<<
" max_concurrent_streams="
<<
s
.
max_concurrent_streams
<<
" initial_window_size="
<<
s
.
initial_window_size
<<
" max_frame_size="
<<
s
.
max_frame_size
<<
" max_header_list_size="
<<
s
.
max_header_list_size
<<
'}'
;
return
os
;
}
const
char
*
H2ErrorToString
(
H2Error
e
)
{
...
...
@@ -202,5 +59,4 @@ const char* H2ErrorToString(H2Error e) {
return
"Unknown-H2Error"
;
}
}
// namespace brpc
src/brpc/http2.h
View file @
8994b65a
...
...
@@ -23,6 +23,9 @@
namespace
brpc
{
struct
H2Settings
{
// Construct with default values.
H2Settings
();
// Allows the sender to inform the remote endpoint of the maximum size of
// the header compression table used to decode header blocks, in octets.
// The encoder can select any size equal to or less than this value by
...
...
@@ -79,35 +82,9 @@ struct H2Settings {
// enforced.
// Default: unlimited.
uint32_t
max_header_list_size
;
// Construct with default values.
H2Settings
();
// True iff all fields are valid.
bool
IsValid
()
const
;
// [ https://tools.ietf.org/html/rfc7540#section-6.5.1 ]
// Parse from n bytes from the iterator.
// Returns true on success.
bool
ParseFrom
(
butil
::
IOBufBytesIterator
&
,
size_t
n
);
// Bytes of serialized data.
size_t
ByteSize
()
const
;
// Maximum value that may be returned by ByteSize().
static
const
size_t
MAX_BYTE_SIZE
=
36
;
// Serialize to `out' which is at least ByteSize() bytes long.
// Returns bytes written.
size_t
SerializeTo
(
void
*
out
)
const
;
void
Print
(
std
::
ostream
&
)
const
;
};
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
H2Settings
&
s
)
{
s
.
Print
(
os
);
return
os
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
H2Settings
&
s
);
enum
H2Error
{
H2_NO_ERROR
=
0x0
,
// Graceful shutdown
...
...
src/brpc/policy/http2_rpc_protocol.cpp
View file @
8994b65a
...
...
@@ -136,6 +136,110 @@ struct H2FrameHead {
static
void
InitFrameHandlers
();
// [ https://tools.ietf.org/html/rfc7540#section-6.5.1 ]
enum
H2SettingsIdentifier
{
HTTP2_SETTINGS_HEADER_TABLE_SIZE
=
0x1
,
HTTP2_SETTINGS_ENABLE_PUSH
=
0x2
,
HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
=
0x3
,
HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
=
0x4
,
HTTP2_SETTINGS_MAX_FRAME_SIZE
=
0x5
,
HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
=
0x6
};
// Parse from n bytes from the iterator.
// Returns true on success.
bool
ParseH2Settings
(
H2Settings
*
out
,
butil
::
IOBufBytesIterator
&
it
,
size_t
n
)
{
const
uint32_t
npairs
=
n
/
6
;
if
(
npairs
*
6
!=
n
)
{
LOG
(
ERROR
)
<<
"Invalid payload_size="
<<
n
;
return
false
;
}
for
(
uint32_t
i
=
0
;
i
<
npairs
;
++
i
)
{
uint16_t
id
=
LoadUint16
(
it
);
uint32_t
value
=
LoadUint32
(
it
);
switch
(
static_cast
<
H2SettingsIdentifier
>
(
id
))
{
case
HTTP2_SETTINGS_HEADER_TABLE_SIZE
:
out
->
header_table_size
=
value
;
break
;
case
HTTP2_SETTINGS_ENABLE_PUSH
:
if
(
value
>
1
)
{
LOG
(
ERROR
)
<<
"Invalid value="
<<
value
<<
" for ENABLE_PUSH"
;
return
false
;
}
out
->
enable_push
=
value
;
break
;
case
HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
:
out
->
max_concurrent_streams
=
value
;
break
;
case
HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
:
if
(
value
>
H2Settings
::
MAX_INITIAL_WINDOW_SIZE
)
{
LOG
(
ERROR
)
<<
"Invalid initial_window_size="
<<
value
;
return
false
;
}
out
->
initial_window_size
=
value
;
break
;
case
HTTP2_SETTINGS_MAX_FRAME_SIZE
:
if
(
value
>
H2Settings
::
MAX_OF_MAX_FRAME_SIZE
||
value
<
H2Settings
::
DEFAULT_MAX_FRAME_SIZE
)
{
LOG
(
ERROR
)
<<
"Invalid max_frame_size="
<<
value
;
return
false
;
}
out
->
max_frame_size
=
value
;
break
;
case
HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
:
out
->
max_header_list_size
=
value
;
break
;
default:
// An endpoint that receives a SETTINGS frame with any unknown or
// unsupported identifier MUST ignore that setting (section 6.5.2)
LOG
(
WARNING
)
<<
"Unknown setting, id="
<<
id
<<
" value="
<<
value
;
break
;
}
}
return
true
;
}
// Maximum value that may be returned by SerializeH2Settings
static
const
size_t
H2_SETTINGS_MAX_BYTE_SIZE
=
36
;
// Serialize to `out' which is at least ByteSize() bytes long.
// Returns bytes written.
size_t
SerializeH2Settings
(
const
H2Settings
&
in
,
void
*
out
)
{
uint8_t
*
p
=
(
uint8_t
*
)
out
;
if
(
in
.
header_table_size
!=
H2Settings
::
DEFAULT_HEADER_TABLE_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_HEADER_TABLE_SIZE
);
SaveUint32
(
p
+
2
,
in
.
header_table_size
);
p
+=
6
;
}
if
(
in
.
enable_push
!=
H2Settings
::
DEFAULT_ENABLE_PUSH
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_ENABLE_PUSH
);
SaveUint32
(
p
+
2
,
in
.
enable_push
);
p
+=
6
;
}
if
(
in
.
max_concurrent_streams
!=
std
::
numeric_limits
<
uint32_t
>::
max
())
{
SaveUint16
(
p
,
HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
);
SaveUint32
(
p
+
2
,
in
.
max_concurrent_streams
);
p
+=
6
;
}
if
(
in
.
initial_window_size
!=
H2Settings
::
DEFAULT_INITIAL_WINDOW_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
);
SaveUint32
(
p
+
2
,
in
.
initial_window_size
);
p
+=
6
;
}
if
(
in
.
max_frame_size
!=
H2Settings
::
DEFAULT_MAX_FRAME_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_MAX_FRAME_SIZE
);
SaveUint32
(
p
+
2
,
in
.
max_frame_size
);
p
+=
6
;
}
if
(
in
.
max_header_list_size
!=
std
::
numeric_limits
<
uint32_t
>::
max
())
{
SaveUint16
(
p
,
HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
);
SaveUint32
(
p
+
2
,
in
.
max_header_list_size
);
p
+=
6
;
}
return
static_cast
<
size_t
>
(
p
-
(
uint8_t
*
)
out
);
}
// Contexts of a http2 connection
class
H2Context
:
public
Destroyable
,
public
Describable
{
public
:
...
...
@@ -384,20 +488,11 @@ H2StreamContext* H2Context::RemoveStream(int stream_id) {
}
H2StreamContext
*
H2Context
::
FindStream
(
int
stream_id
)
{
{
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
H2StreamContext
**
psctx
=
_pending_streams
.
seek
(
stream_id
);
if
(
psctx
)
{
return
*
psctx
;
}
}
/*
if (closed) {
const uint32_t limit = is_client_side() ? _last_client_stream_id
: (uint32_t)_last_server_stream_id;
*closed = ((uint32_t)stream_id < limit);
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
H2StreamContext
**
psctx
=
_pending_streams
.
seek
(
stream_id
);
if
(
psctx
)
{
return
*
psctx
;
}
*/
return
NULL
;
}
...
...
@@ -481,8 +576,9 @@ ParseResult H2Context::Consume(
}
_conn_state
=
H2_CONNECTION_READY
;
char
settingsbuf
[
FRAME_HEAD_SIZE
+
H2Settings
::
MAX_BYTE_SIZE
];
const
size_t
nb
=
_unack_local_settings
.
SerializeTo
(
settingsbuf
+
FRAME_HEAD_SIZE
);
char
settingsbuf
[
FRAME_HEAD_SIZE
+
H2_SETTINGS_MAX_BYTE_SIZE
];
const
size_t
nb
=
SerializeH2Settings
(
_unack_local_settings
,
settingsbuf
+
FRAME_HEAD_SIZE
);
SerializeFrameHead
(
settingsbuf
,
nb
,
H2_FRAME_SETTINGS
,
0
,
0
);
butil
::
IOBuf
buf
;
buf
.
append
(
settingsbuf
,
FRAME_HEAD_SIZE
+
nb
);
...
...
@@ -852,7 +948,7 @@ H2ParseResult H2Context::OnSettings(
return
MakeH2Message
(
NULL
);
}
const
int64_t
old_initial_window_size
=
_remote_settings
.
initial_window_size
;
if
(
!
_remote_settings
.
ParseFrom
(
it
,
frame_head
.
payload_size
))
{
if
(
!
ParseH2Settings
(
&
_remote_settings
,
it
,
frame_head
.
payload_size
))
{
LOG
(
ERROR
)
<<
"Fail to parse from SETTINGS"
;
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
...
...
@@ -1419,9 +1515,9 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
out
->
append
(
H2_CONNECTION_PREFACE_PREFIX
,
H2_CONNECTION_PREFACE_PREFIX_SIZE
);
char
settingsbuf
[
FRAME_HEAD_SIZE
+
H2
Settings
::
MAX_BYTE_SIZE
];
const
size_t
nb
=
ctx
->
_unack_local_settings
.
SerializeTo
(
settingsbuf
+
FRAME_HEAD_SIZE
);
char
settingsbuf
[
FRAME_HEAD_SIZE
+
H2
_SETTINGS_
MAX_BYTE_SIZE
];
const
size_t
nb
=
SerializeH2Settings
(
ctx
->
_unack_local_settings
,
settingsbuf
+
FRAME_HEAD_SIZE
);
SerializeFrameHead
(
settingsbuf
,
nb
,
H2_FRAME_SETTINGS
,
0
,
0
);
out
->
append
(
settingsbuf
,
FRAME_HEAD_SIZE
+
nb
);
}
...
...
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