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
513ed819
Commit
513ed819
authored
Sep 21, 2018
by
gejun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix issues around WINDOW_UPDATE & rpc-timeout does not close the connection
parent
9cf3f779
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
226 additions
and
147 deletions
+226
-147
http2.cpp
src/brpc/http2.cpp
+2
-1
http2.h
src/brpc/http2.h
+7
-1
http2_rpc_protocol.cpp
src/brpc/policy/http2_rpc_protocol.cpp
+199
-138
http2_rpc_protocol.h
src/brpc/policy/http2_rpc_protocol.h
+18
-7
No files found.
src/brpc/http2.cpp
View file @
513ed819
...
@@ -137,7 +137,7 @@ size_t H2Settings::ByteSize() const {
...
@@ -137,7 +137,7 @@ size_t H2Settings::ByteSize() const {
return
size
;
return
size
;
}
}
void
H2Settings
::
SerializeTo
(
void
*
out
)
const
{
size_t
H2Settings
::
SerializeTo
(
void
*
out
)
const
{
uint8_t
*
p
=
(
uint8_t
*
)
out
;
uint8_t
*
p
=
(
uint8_t
*
)
out
;
if
(
header_table_size
!=
DEFAULT_HEADER_TABLE_SIZE
)
{
if
(
header_table_size
!=
DEFAULT_HEADER_TABLE_SIZE
)
{
SaveUint16
(
p
,
HTTP2_SETTINGS_HEADER_TABLE_SIZE
);
SaveUint16
(
p
,
HTTP2_SETTINGS_HEADER_TABLE_SIZE
);
...
@@ -169,6 +169,7 @@ void H2Settings::SerializeTo(void* out) const {
...
@@ -169,6 +169,7 @@ void H2Settings::SerializeTo(void* out) const {
SaveUint32
(
p
+
2
,
max_header_list_size
);
SaveUint32
(
p
+
2
,
max_header_list_size
);
p
+=
6
;
p
+=
6
;
}
}
return
static_cast
<
size_t
>
(
p
-
(
uint8_t
*
)
out
);
}
}
void
H2Settings
::
Print
(
std
::
ostream
&
os
)
const
{
void
H2Settings
::
Print
(
std
::
ostream
&
os
)
const
{
...
...
src/brpc/http2.h
View file @
513ed819
...
@@ -90,10 +90,16 @@ struct H2Settings {
...
@@ -90,10 +90,16 @@ struct H2Settings {
// Parse from n bytes from the iterator.
// Parse from n bytes from the iterator.
// Returns true on success.
// Returns true on success.
bool
ParseFrom
(
butil
::
IOBufBytesIterator
&
,
size_t
n
);
bool
ParseFrom
(
butil
::
IOBufBytesIterator
&
,
size_t
n
);
// Bytes of serialized data.
// Bytes of serialized data.
size_t
ByteSize
()
const
;
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.
// Serialize to `out' which is at least ByteSize() bytes long.
void
SerializeTo
(
void
*
out
)
const
;
// Returns bytes written.
size_t
SerializeTo
(
void
*
out
)
const
;
void
Print
(
std
::
ostream
&
)
const
;
void
Print
(
std
::
ostream
&
)
const
;
};
};
...
...
src/brpc/policy/http2_rpc_protocol.cpp
View file @
513ed819
...
@@ -44,9 +44,6 @@ DEFINE_bool(http2_hpack_encode_name, false,
...
@@ -44,9 +44,6 @@ DEFINE_bool(http2_hpack_encode_name, false,
DEFINE_bool
(
http2_hpack_encode_value
,
false
,
DEFINE_bool
(
http2_hpack_encode_value
,
false
,
"Encode value in HTTP2 headers with huffman encoding"
);
"Encode value in HTTP2 headers with huffman encoding"
);
DEFINE_int32
(
http2_window_update_size
,
2048
,
"Initial window update size for flow control"
);
const
char
*
H2StreamState2Str
(
H2StreamState
s
)
{
const
char
*
H2StreamState2Str
(
H2StreamState
s
)
{
switch
(
s
)
{
switch
(
s
)
{
case
H2_STREAM_IDLE
:
return
"idle"
;
case
H2_STREAM_IDLE
:
return
"idle"
;
...
@@ -174,14 +171,14 @@ public:
...
@@ -174,14 +171,14 @@ public:
void
AddAbandonedStream
(
uint32_t
stream_id
);
void
AddAbandonedStream
(
uint32_t
stream_id
);
//@Destroyable
//@Destroyable
void
Destroy
()
{
delete
this
;
}
void
Destroy
()
override
{
delete
this
;
}
int
AllocateClientStreamId
();
int
AllocateClientStreamId
();
bool
RunOutStreams
()
const
;
bool
RunOutStreams
()
const
;
// Try to map stream_id to ctx if stream_id does not exist before
// Try to map stream_id to ctx if stream_id does not exist before
// Returns true on success, false otherwise.
// Returns true on success, false otherwise.
bool
TryToInsertStream
(
int
stream_id
,
H2StreamContext
*
ctx
);
bool
TryToInsertStream
(
int
stream_id
,
H2StreamContext
*
ctx
);
uint32_t
StreamSize
()
;
uint32_t
VolatilePendingStreamSize
()
const
;
HPacker
&
hpacker
()
{
return
_hpacker
;
}
HPacker
&
hpacker
()
{
return
_hpacker
;
}
const
H2Settings
&
remote_settings
()
const
{
return
_remote_settings
;
}
const
H2Settings
&
remote_settings
()
const
{
return
_remote_settings
;
}
...
@@ -192,7 +189,8 @@ public:
...
@@ -192,7 +189,8 @@ public:
void
Describe
(
std
::
ostream
&
os
,
const
DescribeOptions
&
)
const
;
void
Describe
(
std
::
ostream
&
os
,
const
DescribeOptions
&
)
const
;
void
ReclaimWindowSize
(
int64_t
);
void
DeferWindowUpdate
(
int64_t
);
int64_t
ReleaseDeferredWindowUpdate
();
private
:
private
:
friend
class
H2StreamContext
;
friend
class
H2StreamContext
;
...
@@ -214,17 +212,13 @@ friend void InitFrameHandlers();
...
@@ -214,17 +212,13 @@ friend void InitFrameHandlers();
H2ParseResult
OnContinuation
(
butil
::
IOBufBytesIterator
&
,
const
H2FrameHead
&
);
H2ParseResult
OnContinuation
(
butil
::
IOBufBytesIterator
&
,
const
H2FrameHead
&
);
H2StreamContext
*
RemoveStream
(
int
stream_id
);
H2StreamContext
*
RemoveStream
(
int
stream_id
);
H2StreamContext
*
FindStream
(
int
stream_id
,
bool
*
closed
);
H2StreamContext
*
FindStream
(
int
stream_id
);
H2StreamContext
*
FindStream
(
int
stream_id
)
{
return
FindStream
(
stream_id
,
NULL
);
}
void
ClearAbandonedStreamsImpl
();
void
ClearAbandonedStreamsImpl
();
// True if the connection is established by client, otherwise it's
// True if the connection is established by client, otherwise it's
// accepted by server.
// accepted by server.
Socket
*
_socket
;
Socket
*
_socket
;
butil
::
atomic
<
int64_t
>
_remote_
conn_window_size
;
butil
::
atomic
<
int64_t
>
_remote_
window_left
;
H2ConnectionState
_conn_state
;
H2ConnectionState
_conn_state
;
int
_last_server_stream_id
;
int
_last_server_stream_id
;
uint32_t
_last_client_stream_id
;
uint32_t
_last_client_stream_id
;
...
@@ -232,15 +226,15 @@ friend void InitFrameHandlers();
...
@@ -232,15 +226,15 @@ friend void InitFrameHandlers();
H2Settings
_local_settings
;
H2Settings
_local_settings
;
H2Settings
_unack_local_settings
;
H2Settings
_unack_local_settings
;
HPacker
_hpacker
;
HPacker
_hpacker
;
butil
::
Mutex
_abandoned_streams_mutex
;
mutable
butil
::
Mutex
_abandoned_streams_mutex
;
std
::
vector
<
uint32_t
>
_abandoned_streams
;
std
::
vector
<
uint32_t
>
_abandoned_streams
;
typedef
butil
::
FlatMap
<
int
,
H2StreamContext
*>
StreamMap
;
typedef
butil
::
FlatMap
<
int
,
H2StreamContext
*>
StreamMap
;
butil
::
Mutex
_stream_mutex
;
mutable
butil
::
Mutex
_stream_mutex
;
StreamMap
_pending_streams
;
StreamMap
_pending_streams
;
butil
::
atomic
<
int64_t
>
_
pending_conn_window_siz
e
;
butil
::
atomic
<
int64_t
>
_
deferred_window_updat
e
;
};
};
inline
bool
add_window_s
ize
(
butil
::
atomic
<
int64_t
>*
window_size
,
int64_t
diff
)
{
inline
bool
AddWindowS
ize
(
butil
::
atomic
<
int64_t
>*
window_size
,
int64_t
diff
)
{
// A sender MUST NOT allow a flow-control window to exceed 2^31 - 1.
// A sender MUST NOT allow a flow-control window to exceed 2^31 - 1.
// If a sender receives a WINDOW_UPDATE that causes a flow-control window
// If a sender receives a WINDOW_UPDATE that causes a flow-control window
// to exceed this maximum, it MUST terminate either the stream or the connection,
// to exceed this maximum, it MUST terminate either the stream or the connection,
...
@@ -262,7 +256,7 @@ inline bool add_window_size(butil::atomic<int64_t>* window_size, int64_t diff) {
...
@@ -262,7 +256,7 @@ inline bool add_window_size(butil::atomic<int64_t>* window_size, int64_t diff) {
return
true
;
return
true
;
}
}
inline
bool
consume_window_s
ize
(
butil
::
atomic
<
int64_t
>*
window_size
,
int64_t
size
)
{
inline
bool
MinusWindowS
ize
(
butil
::
atomic
<
int64_t
>*
window_size
,
int64_t
size
)
{
if
(
window_size
->
load
(
butil
::
memory_order_relaxed
)
<
size
)
{
if
(
window_size
->
load
(
butil
::
memory_order_relaxed
)
<
size
)
{
// false negative is OK.
// false negative is OK.
return
false
;
return
false
;
...
@@ -300,11 +294,11 @@ inline H2Context::FrameHandler FindFrameHandler(H2FrameType type) {
...
@@ -300,11 +294,11 @@ inline H2Context::FrameHandler FindFrameHandler(H2FrameType type) {
H2Context
::
H2Context
(
Socket
*
socket
,
const
Server
*
server
)
H2Context
::
H2Context
(
Socket
*
socket
,
const
Server
*
server
)
:
_socket
(
socket
)
:
_socket
(
socket
)
,
_remote_
conn_window_size
(
H2Settings
::
DEFAULT_INITIAL_WINDOW_SIZE
)
,
_remote_
window_left
(
H2Settings
::
DEFAULT_INITIAL_WINDOW_SIZE
)
,
_conn_state
(
H2_CONNECTION_UNINITIALIZED
)
,
_conn_state
(
H2_CONNECTION_UNINITIALIZED
)
,
_last_server_stream_id
(
-
1
)
,
_last_server_stream_id
(
-
1
)
,
_last_client_stream_id
(
1
)
,
_last_client_stream_id
(
1
)
,
_
pending_conn_window_siz
e
(
0
)
{
,
_
deferred_window_updat
e
(
0
)
{
if
(
server
)
{
if
(
server
)
{
_unack_local_settings
=
server
->
options
().
http2_settings
;
_unack_local_settings
=
server
->
options
().
http2_settings
;
}
else
{
}
else
{
...
@@ -329,12 +323,12 @@ H2Context::~H2Context() {
...
@@ -329,12 +323,12 @@ H2Context::~H2Context() {
H2StreamContext
::
H2StreamContext
()
H2StreamContext
::
H2StreamContext
()
:
_conn_ctx
(
NULL
)
:
_conn_ctx
(
NULL
)
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
,
_state
(
H2_STREAM_IDLE
)
,
_state
(
H2_STREAM_IDLE
)
#endif
#endif
,
_stream_ended
(
false
)
,
_stream_ended
(
false
)
,
_remote_window_
size
(
0
)
,
_remote_window_
left
(
0
)
,
_
local_window_siz
e
(
0
)
,
_
deferred_window_updat
e
(
0
)
,
_correlation_id
(
INVALID_BTHREAD_ID
.
value
)
{
,
_correlation_id
(
INVALID_BTHREAD_ID
.
value
)
{
header
().
set_version
(
2
,
0
);
header
().
set_version
(
2
,
0
);
#ifndef NDEBUG
#ifndef NDEBUG
...
@@ -343,15 +337,33 @@ H2StreamContext::H2StreamContext()
...
@@ -343,15 +337,33 @@ H2StreamContext::H2StreamContext()
}
}
H2StreamContext
::~
H2StreamContext
()
{
H2StreamContext
::~
H2StreamContext
()
{
if
(
_conn_ctx
)
{
int64_t
diff
=
_conn_ctx
->
local_settings
().
initial_window_size
-
_local_window_size
;
_conn_ctx
->
ReclaimWindowSize
(
diff
);
}
#ifndef NDEBUG
#ifndef NDEBUG
get_http2_bvars
()
->
h2_stream_context_count
<<
-
1
;
get_http2_bvars
()
->
h2_stream_context_count
<<
-
1
;
#endif
#endif
}
}
bool
H2StreamContext
::
ConsumeWindowSize
(
int64_t
size
)
{
// This method is guaranteed to be called in AppendAndDestroySelf() which
// is run sequentially. As a result, _remote_window_left of this stream
// context will not be decremented (may be incremented) because following
// AppendAndDestroySelf() are not run yet.
// This fact is important to make window_size changes to stream and
// connection contexts transactionally.
if
(
_remote_window_left
.
load
(
butil
::
memory_order_relaxed
)
<
size
)
{
return
false
;
}
if
(
!
MinusWindowSize
(
&
_conn_ctx
->
_remote_window_left
,
size
))
{
return
false
;
}
int64_t
after_sub
=
_remote_window_left
.
fetch_sub
(
size
,
butil
::
memory_order_relaxed
)
-
size
;
if
(
after_sub
<
0
)
{
LOG
(
FATAL
)
<<
"Impossible, the http2 impl is buggy"
;
_remote_window_left
.
fetch_add
(
size
,
butil
::
memory_order_relaxed
);
return
false
;
}
return
true
;
}
int
H2Context
::
Init
()
{
int
H2Context
::
Init
()
{
if
(
_pending_streams
.
init
(
64
,
70
)
!=
0
)
{
if
(
_pending_streams
.
init
(
64
,
70
)
!=
0
)
{
LOG
(
ERROR
)
<<
"Fail to init _pending_streams"
;
LOG
(
ERROR
)
<<
"Fail to init _pending_streams"
;
...
@@ -386,7 +398,7 @@ H2StreamContext* H2Context::RemoveStream(int stream_id) {
...
@@ -386,7 +398,7 @@ H2StreamContext* H2Context::RemoveStream(int stream_id) {
return
NULL
;
return
NULL
;
}
}
H2StreamContext
*
H2Context
::
FindStream
(
int
stream_id
,
bool
*
closed
)
{
H2StreamContext
*
H2Context
::
FindStream
(
int
stream_id
)
{
{
{
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
H2StreamContext
**
psctx
=
_pending_streams
.
seek
(
stream_id
);
H2StreamContext
**
psctx
=
_pending_streams
.
seek
(
stream_id
);
...
@@ -394,11 +406,13 @@ H2StreamContext* H2Context::FindStream(int stream_id, bool* closed) {
...
@@ -394,11 +406,13 @@ H2StreamContext* H2Context::FindStream(int stream_id, bool* closed) {
return
*
psctx
;
return
*
psctx
;
}
}
}
}
/*
if (closed) {
if (closed) {
const uint32_t limit = is_client_side() ? _last_client_stream_id
const uint32_t limit = is_client_side() ? _last_client_stream_id
: (uint32_t)_last_server_stream_id;
: (uint32_t)_last_server_stream_id;
*closed = ((uint32_t)stream_id < limit);
*closed = ((uint32_t)stream_id < limit);
}
}
*/
return
NULL
;
return
NULL
;
}
}
...
@@ -412,8 +426,7 @@ bool H2Context::TryToInsertStream(int stream_id, H2StreamContext* ctx) {
...
@@ -412,8 +426,7 @@ bool H2Context::TryToInsertStream(int stream_id, H2StreamContext* ctx) {
return
false
;
return
false
;
}
}
uint32_t
H2Context
::
StreamSize
()
{
inline
uint32_t
H2Context
::
VolatilePendingStreamSize
()
const
{
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
return
_pending_streams
.
size
();
return
_pending_streams
.
size
();
}
}
...
@@ -483,14 +496,11 @@ ParseResult H2Context::Consume(
...
@@ -483,14 +496,11 @@ ParseResult H2Context::Consume(
}
}
_conn_state
=
H2_CONNECTION_READY
;
_conn_state
=
H2_CONNECTION_READY
;
char
settingbuf
[
36
];
char
settingsbuf
[
FRAME_HEAD_SIZE
+
H2Settings
::
MAX_BYTE_SIZE
];
_unack_local_settings
.
SerializeTo
(
settingbuf
);
const
size_t
nb
=
_unack_local_settings
.
SerializeTo
(
settingsbuf
+
FRAME_HEAD_SIZE
);
char
headbuf
[
FRAME_HEAD_SIZE
];
SerializeFrameHead
(
settingsbuf
,
nb
,
H2_FRAME_SETTINGS
,
0
,
0
);
SerializeFrameHead
(
headbuf
,
_unack_local_settings
.
ByteSize
(),
H2_FRAME_SETTINGS
,
0
,
0
);
butil
::
IOBuf
buf
;
butil
::
IOBuf
buf
;
buf
.
append
(
headbuf
,
FRAME_HEAD_SIZE
);
buf
.
append
(
settingsbuf
,
FRAME_HEAD_SIZE
+
nb
);
buf
.
append
(
settingbuf
,
_unack_local_settings
.
ByteSize
());
Socket
::
WriteOptions
wopt
;
Socket
::
WriteOptions
wopt
;
wopt
.
ignore_eovercrowded
=
true
;
wopt
.
ignore_eovercrowded
=
true
;
if
(
socket
->
Write
(
&
buf
,
&
wopt
)
!=
0
)
{
if
(
socket
->
Write
(
&
buf
,
&
wopt
)
!=
0
)
{
...
@@ -604,8 +614,13 @@ H2ParseResult H2Context::OnHeaders(
...
@@ -604,8 +614,13 @@ H2ParseResult H2Context::OnHeaders(
}
else
{
}
else
{
sctx
=
FindStream
(
frame_head
.
stream_id
);
sctx
=
FindStream
(
frame_head
.
stream_id
);
if
(
sctx
==
NULL
)
{
if
(
sctx
==
NULL
)
{
LOG
(
ERROR
)
<<
"stream_id="
<<
frame_head
.
stream_id
if
(
is_client_side
())
{
<<
" does not exist"
;
// Ignore the message without closing the socket.
H2StreamContext
tmp_sctx
(
this
,
frame_head
.
stream_id
);
tmp_sctx
.
OnHeaders
(
it
,
frame_head
,
frag_size
,
pad_length
);
return
MakeH2Message
(
NULL
);
}
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
}
}
}
...
@@ -616,7 +631,7 @@ H2ParseResult H2StreamContext::OnHeaders(
...
@@ -616,7 +631,7 @@ H2ParseResult H2StreamContext::OnHeaders(
butil
::
IOBufBytesIterator
&
it
,
const
H2FrameHead
&
frame_head
,
butil
::
IOBufBytesIterator
&
it
,
const
H2FrameHead
&
frame_head
,
uint32_t
frag_size
,
uint8_t
pad_length
)
{
uint32_t
frag_size
,
uint8_t
pad_length
)
{
_parsed_length
+=
FRAME_HEAD_SIZE
+
frame_head
.
payload_size
;
_parsed_length
+=
FRAME_HEAD_SIZE
+
frame_head
.
payload_size
;
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
SetState
(
H2_STREAM_OPEN
);
SetState
(
H2_STREAM_OPEN
);
#endif
#endif
butil
::
IOBufBytesIterator
it2
(
it
,
frag_size
);
butil
::
IOBufBytesIterator
it2
(
it
,
frag_size
);
...
@@ -640,18 +655,25 @@ H2ParseResult H2StreamContext::OnHeaders(
...
@@ -640,18 +655,25 @@ H2ParseResult H2StreamContext::OnHeaders(
return
EndRemoteStream
();
return
EndRemoteStream
();
}
}
return
MakeH2Message
(
NULL
);
return
MakeH2Message
(
NULL
);
}
else
{
if
(
frame_head
.
flags
&
H2_FLAGS_END_STREAM
)
{
// Delay calling EndRemoteStream() in OnContinuation()
_stream_ended
=
true
;
}
return
MakeH2Message
(
NULL
);
}
}
if
(
frame_head
.
flags
&
H2_FLAGS_END_STREAM
)
{
// Delay calling EndRemoteStream() in OnContinuation()
_stream_ended
=
true
;
}
return
MakeH2Message
(
NULL
);
}
}
H2ParseResult
H2Context
::
OnContinuation
(
H2ParseResult
H2Context
::
OnContinuation
(
butil
::
IOBufBytesIterator
&
it
,
const
H2FrameHead
&
frame_head
)
{
butil
::
IOBufBytesIterator
&
it
,
const
H2FrameHead
&
frame_head
)
{
H2StreamContext
*
sctx
=
FindStream
(
frame_head
.
stream_id
);
H2StreamContext
*
sctx
=
FindStream
(
frame_head
.
stream_id
);
if
(
sctx
==
NULL
)
{
if
(
sctx
==
NULL
)
{
if
(
is_client_side
())
{
// Ignore the message without closing the socket.
H2StreamContext
tmp_sctx
(
this
,
frame_head
.
stream_id
);
tmp_sctx
.
OnContinuation
(
it
,
frame_head
);
return
MakeH2Message
(
NULL
);
}
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
}
...
@@ -697,6 +719,13 @@ H2ParseResult H2Context::OnData(
...
@@ -697,6 +719,13 @@ H2ParseResult H2Context::OnData(
frag_size
-=
pad_length
;
frag_size
-=
pad_length
;
H2StreamContext
*
sctx
=
FindStream
(
frame_head
.
stream_id
);
H2StreamContext
*
sctx
=
FindStream
(
frame_head
.
stream_id
);
if
(
sctx
==
NULL
)
{
if
(
sctx
==
NULL
)
{
if
(
is_client_side
())
{
// Ignore the message without closing the socket.
H2StreamContext
tmp_sctx
(
this
,
frame_head
.
stream_id
);
tmp_sctx
.
OnData
(
it
,
frame_head
,
frag_size
,
pad_length
);
DeferWindowUpdate
(
tmp_sctx
.
ReleaseDeferredWindowUpdate
());
return
MakeH2Message
(
NULL
);
}
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
return
MakeH2Message
(
NULL
);
return
MakeH2Message
(
NULL
);
}
}
...
@@ -717,23 +746,23 @@ H2ParseResult H2StreamContext::OnData(
...
@@ -717,23 +746,23 @@ H2ParseResult H2StreamContext::OnData(
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
}
}
}
int64_t
before_sub
=
_local_window_size
.
fetch_sub
(
frag_size
,
butil
::
memory_order_relaxed
);
const
int64_t
acc
=
_deferred_window_update
.
fetch_add
(
frag_size
,
butil
::
memory_order_relaxed
)
+
frag_size
;
// HTTP/2 defines only the format and semantics of the WINDOW_UPDATE frame (Section 6.9).
if
(
acc
>=
_conn_ctx
->
local_settings
().
initial_window_size
/
2
)
{
// Spec does not stipulate how a receiver decides when to send this frame or the value
// Rarely happen for small messages.
// that it sends, nor does it specify how a sender chooses to send packets.
const
int64_t
stream_wu
=
// Implementations are able to select any algorithm that suits their needs.
_deferred_window_update
.
exchange
(
0
,
butil
::
memory_order_relaxed
);
if
(
before_sub
<
_conn_ctx
->
local_settings
().
initial_window_size
/
3
)
{
const
int64_t
conn_wu
=
stream_wu
+
_conn_ctx
->
ReleaseDeferredWindowUpdate
();
int64_t
old_value
=
_local_window_size
.
exchange
(
_conn_ctx
->
local_settings
().
initial_window_size
,
butil
::
memory_order_relaxed
);
char
winbuf
[(
FRAME_HEAD_SIZE
+
4
)
*
2
];
char
swinbuf
[
FRAME_HEAD_SIZE
+
4
];
SerializeFrameHead
(
winbuf
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
stream_id
());
SerializeFrameHead
(
swinbuf
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
stream_id
());
SaveUint32
(
winbuf
+
FRAME_HEAD_SIZE
,
stream_wu
);
SaveUint32
(
swinbuf
+
FRAME_HEAD_SIZE
,
_local_window_size
-
old_value
);
char
cwinbuf
[
FRAME_HEAD_SIZE
+
4
];
char
*
cwin
=
winbuf
+
FRAME_HEAD_SIZE
+
4
;
SerializeFrameHead
(
cwinbuf
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
0
);
SerializeFrameHead
(
cwin
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
0
);
SaveUint32
(
cwinbuf
+
FRAME_HEAD_SIZE
,
_local_window_size
-
old_value
);
SaveUint32
(
cwin
+
FRAME_HEAD_SIZE
,
conn_wu
);
butil
::
IOBuf
sendbuf
;
butil
::
IOBuf
sendbuf
;
sendbuf
.
append
(
swinbuf
,
sizeof
(
swinbuf
));
sendbuf
.
append
(
winbuf
,
sizeof
(
winbuf
));
sendbuf
.
append
(
cwinbuf
,
sizeof
(
cwinbuf
));
Socket
::
WriteOptions
wopt
;
Socket
::
WriteOptions
wopt
;
wopt
.
ignore_eovercrowded
=
true
;
wopt
.
ignore_eovercrowded
=
true
;
if
(
_conn_ctx
->
_socket
->
Write
(
&
sendbuf
,
&
wopt
)
!=
0
)
{
if
(
_conn_ctx
->
_socket
->
Write
(
&
sendbuf
,
&
wopt
)
!=
0
)
{
...
@@ -765,7 +794,7 @@ H2ParseResult H2Context::OnResetStream(
...
@@ -765,7 +794,7 @@ H2ParseResult H2Context::OnResetStream(
H2ParseResult
H2StreamContext
::
OnResetStream
(
H2ParseResult
H2StreamContext
::
OnResetStream
(
H2Error
h2_error
,
const
H2FrameHead
&
frame_head
)
{
H2Error
h2_error
,
const
H2FrameHead
&
frame_head
)
{
_parsed_length
+=
FRAME_HEAD_SIZE
+
frame_head
.
payload_size
;
_parsed_length
+=
FRAME_HEAD_SIZE
+
frame_head
.
payload_size
;
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
if
(
state
()
==
H2_STREAM_OPEN
)
{
if
(
state
()
==
H2_STREAM_OPEN
)
{
SetState
(
H2_STREAM_HALF_CLOSED_REMOTE
);
SetState
(
H2_STREAM_HALF_CLOSED_REMOTE
);
}
else
if
(
state
()
==
H2_STREAM_HALF_CLOSED_LOCAL
)
{
}
else
if
(
state
()
==
H2_STREAM_HALF_CLOSED_LOCAL
)
{
...
@@ -793,7 +822,7 @@ H2ParseResult H2StreamContext::OnResetStream(
...
@@ -793,7 +822,7 @@ H2ParseResult H2StreamContext::OnResetStream(
}
}
H2ParseResult
H2StreamContext
::
EndRemoteStream
()
{
H2ParseResult
H2StreamContext
::
EndRemoteStream
()
{
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
if
(
state
()
==
H2_STREAM_OPEN
)
{
if
(
state
()
==
H2_STREAM_OPEN
)
{
SetState
(
H2_STREAM_HALF_CLOSED_REMOTE
);
SetState
(
H2_STREAM_HALF_CLOSED_REMOTE
);
}
else
if
(
state
()
==
H2_STREAM_HALF_CLOSED_LOCAL
)
{
}
else
if
(
state
()
==
H2_STREAM_HALF_CLOSED_LOCAL
)
{
...
@@ -804,12 +833,16 @@ H2ParseResult H2StreamContext::EndRemoteStream() {
...
@@ -804,12 +833,16 @@ H2ParseResult H2StreamContext::EndRemoteStream() {
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
}
#endif
#endif
OnMessageComplete
();
H2StreamContext
*
sctx
=
_conn_ctx
->
RemoveStream
(
stream_id
());
H2StreamContext
*
sctx
=
_conn_ctx
->
RemoveStream
(
stream_id
());
if
(
sctx
==
NULL
)
{
if
(
sctx
==
NULL
)
{
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
stream_id
();
return
MakeH2Message
(
NULL
);
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
}
// The remote stream will not send any more data, sending back the
// stream-level WINDOW_UPDATE is pointless, just move the value into
// the connection.
_conn_ctx
->
DeferWindowUpdate
(
sctx
->
ReleaseDeferredWindowUpdate
());
OnMessageComplete
();
return
MakeH2Message
(
sctx
);
return
MakeH2Message
(
sctx
);
}
}
...
@@ -842,12 +875,14 @@ H2ParseResult H2Context::OnSettings(
...
@@ -842,12 +875,14 @@ H2ParseResult H2Context::OnSettings(
static_cast
<
int64_t
>
(
_remote_settings
.
initial_window_size
)
static_cast
<
int64_t
>
(
_remote_settings
.
initial_window_size
)
-
old_initial_window_size
;
-
old_initial_window_size
;
if
(
window_diff
)
{
if
(
window_diff
)
{
// Do not update the connection flow-control window here, which can only be
// Do not update the connection flow-control window here, which can only
// changed using WINDOW_UPDATE frames.
// be changed using WINDOW_UPDATE frames.
// https://tools.ietf.org/html/rfc7540#section-6.9.2
// TODO(gejun): Has race conditions with AppendAndDestroySelf
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
std
::
unique_lock
<
butil
::
Mutex
>
mu
(
_stream_mutex
);
for
(
StreamMap
::
const_iterator
it
=
_pending_streams
.
begin
();
for
(
StreamMap
::
const_iterator
it
=
_pending_streams
.
begin
();
it
!=
_pending_streams
.
end
();
++
it
)
{
it
!=
_pending_streams
.
end
();
++
it
)
{
if
(
!
add_window_size
(
&
it
->
second
->
_remote_window_size
,
window_diff
))
{
if
(
!
AddWindowSize
(
&
it
->
second
->
_remote_window_left
,
window_diff
))
{
return
MakeH2Error
(
H2_FLOW_CONTROL_ERROR
);
return
MakeH2Error
(
H2_FLOW_CONTROL_ERROR
);
}
}
}
}
...
@@ -926,17 +961,17 @@ H2ParseResult H2Context::OnWindowUpdate(
...
@@ -926,17 +961,17 @@ H2ParseResult H2Context::OnWindowUpdate(
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
return
MakeH2Error
(
H2_PROTOCOL_ERROR
);
}
}
if
(
frame_head
.
stream_id
==
0
)
{
if
(
frame_head
.
stream_id
==
0
)
{
if
(
!
add_window_size
(
&
_remote_conn_window_size
,
inc
))
{
if
(
!
AddWindowSize
(
&
_remote_window_left
,
inc
))
{
LOG
(
ERROR
)
<<
"Invalid window_size_increment="
<<
inc
;
LOG
(
ERROR
)
<<
"Invalid window_size_increment="
<<
inc
;
return
MakeH2Error
(
H2_FLOW_CONTROL_ERROR
);
return
MakeH2Error
(
H2_FLOW_CONTROL_ERROR
);
}
}
}
else
{
}
else
{
H2StreamContext
*
sctx
=
FindStream
(
frame_head
.
stream_id
);
H2StreamContext
*
sctx
=
FindStream
(
frame_head
.
stream_id
);
if
(
sctx
==
NULL
)
{
if
(
sctx
==
NULL
)
{
LOG
(
ERROR
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
LOG
(
WARNING
)
<<
"Fail to find stream_id="
<<
frame_head
.
stream_id
;
return
MakeH2Message
(
NULL
);
return
MakeH2Message
(
NULL
);
}
}
if
(
!
add_window_size
(
&
sctx
->
_remote_window_size
,
inc
))
{
if
(
!
AddWindowSize
(
&
sctx
->
_remote_window_left
,
inc
))
{
LOG
(
ERROR
)
<<
"Invalid window_size_increment="
<<
inc
;
LOG
(
ERROR
)
<<
"Invalid window_size_increment="
<<
inc
;
return
MakeH2Error
(
H2_FLOW_CONTROL_ERROR
);
return
MakeH2Error
(
H2_FLOW_CONTROL_ERROR
);
}
}
...
@@ -949,7 +984,8 @@ void H2Context::Describe(std::ostream& os, const DescribeOptions& opt) const {
...
@@ -949,7 +984,8 @@ void H2Context::Describe(std::ostream& os, const DescribeOptions& opt) const {
os
<<
'\n'
;
os
<<
'\n'
;
}
}
const
char
sep
=
(
opt
.
verbose
?
'\n'
:
' '
);
const
char
sep
=
(
opt
.
verbose
?
'\n'
:
' '
);
os
<<
"remote_conn_window_size="
<<
_remote_conn_window_size
os
<<
"remote_window_left="
<<
_remote_window_left
.
load
(
butil
::
memory_order_relaxed
)
<<
sep
<<
"deferred_window_update="
<<
_deferred_window_update
.
load
(
butil
::
memory_order_relaxed
)
<<
sep
<<
"conn_state="
<<
H2ConnectionState2Str
(
_conn_state
);
<<
sep
<<
"conn_state="
<<
H2ConnectionState2Str
(
_conn_state
);
if
(
is_server_side
())
{
if
(
is_server_side
())
{
os
<<
sep
<<
"last_server_stream_id="
<<
_last_server_stream_id
;
os
<<
sep
<<
"last_server_stream_id="
<<
_last_server_stream_id
;
...
@@ -962,30 +998,40 @@ void H2Context::Describe(std::ostream& os, const DescribeOptions& opt) const {
...
@@ -962,30 +998,40 @@ void H2Context::Describe(std::ostream& os, const DescribeOptions& opt) const {
IndentingOStream
os2
(
os
,
2
);
IndentingOStream
os2
(
os
,
2
);
_hpacker
.
Describe
(
os2
,
opt
);
_hpacker
.
Describe
(
os2
,
opt
);
os
<<
'}'
;
os
<<
'}'
;
size_t
abandoned_size
=
0
;
{
BAIDU_SCOPED_LOCK
(
_abandoned_streams_mutex
);
abandoned_size
=
_abandoned_streams
.
size
();
}
os
<<
sep
<<
"abandoned_streams="
<<
abandoned_size
<<
sep
<<
"pending_streams="
<<
VolatilePendingStreamSize
();
if
(
opt
.
verbose
)
{
if
(
opt
.
verbose
)
{
os
<<
'\n'
;
os
<<
'\n'
;
}
}
}
}
void
H2Context
::
ReclaimWindowSize
(
int64_t
size
)
{
inline
int64_t
H2Context
::
ReleaseDeferredWindowUpdate
()
{
if
(
_deferred_window_update
.
load
(
butil
::
memory_order_relaxed
)
==
0
)
{
return
0
;
}
return
_deferred_window_update
.
exchange
(
0
,
butil
::
memory_order_relaxed
);
}
void
H2Context
::
DeferWindowUpdate
(
int64_t
size
)
{
if
(
size
<=
0
)
{
if
(
size
<=
0
)
{
return
;
return
;
}
}
// HTTP/2 defines only the format and semantics of the WINDOW_UPDATE frame (Section 6.9).
const
int64_t
acc
=
_deferred_window_update
.
fetch_add
(
size
,
butil
::
memory_order_relaxed
)
+
size
;
// Spec does not stipulate how a receiver decides when to send this frame or the value
if
(
acc
>=
local_settings
().
initial_window_size
/
2
)
{
// that it sends, nor does it specify how a sender chooses to send packets.
// Rarely happen for small messages.
// Implementations are able to select any algorithm that suits their needs.
const
int64_t
conn_wu
=
_deferred_window_update
.
exchange
(
0
,
butil
::
memory_order_relaxed
);
int64_t
window_update_size
=
0
;
if
(
_pending_conn_window_size
.
fetch_add
(
size
)
>
FLAGS_http2_window_update_size
)
{
char
winbuf
[
FRAME_HEAD_SIZE
+
4
];
window_update_size
=
SerializeFrameHead
(
winbuf
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
0
);
_pending_conn_window_size
.
exchange
(
0
,
butil
::
memory_order_relaxed
);
SaveUint32
(
winbuf
+
FRAME_HEAD_SIZE
,
conn_wu
);
}
if
(
window_update_size
>
0
)
{
char
cwinbuf
[
FRAME_HEAD_SIZE
+
4
];
SerializeFrameHead
(
cwinbuf
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
0
);
SaveUint32
(
cwinbuf
+
FRAME_HEAD_SIZE
,
window_update_size
);
butil
::
IOBuf
sendbuf
;
butil
::
IOBuf
sendbuf
;
sendbuf
.
append
(
cwinbuf
,
sizeof
(
c
winbuf
));
sendbuf
.
append
(
winbuf
,
sizeof
(
winbuf
));
Socket
::
WriteOptions
wopt
;
Socket
::
WriteOptions
wopt
;
wopt
.
ignore_eovercrowded
=
true
;
wopt
.
ignore_eovercrowded
=
true
;
if
(
_socket
->
Write
(
&
sendbuf
,
&
wopt
)
!=
0
)
{
if
(
_socket
->
Write
(
&
sendbuf
,
&
wopt
)
!=
0
)
{
...
@@ -994,15 +1040,17 @@ void H2Context::ReclaimWindowSize(int64_t size) {
...
@@ -994,15 +1040,17 @@ void H2Context::ReclaimWindowSize(int64_t size) {
}
}
}
}
/*
#if defined(BRPC_PROFILE_H2)
bvar
::
Adder
<
int64_t
>
g_parse_time
;
bvar
::
Adder
<
int64_t
>
g_parse_time
;
bvar
::
PerSecond
<
bvar
::
Adder
<
int64_t
>
>
g_parse_time_per_second
(
bvar
::
PerSecond
<
bvar
::
Adder
<
int64_t
>
>
g_parse_time_per_second
(
"h2_parse_second"
,
&
g_parse_time
);
"h2_parse_second"
,
&
g_parse_time
);
*/
#endif
ParseResult
ParseH2Message
(
butil
::
IOBuf
*
source
,
Socket
*
socket
,
ParseResult
ParseH2Message
(
butil
::
IOBuf
*
source
,
Socket
*
socket
,
bool
read_eof
,
const
void
*
arg
)
{
bool
read_eof
,
const
void
*
arg
)
{
//bvar::ScopedTimer<bvar::Adder<int64_t> > tm(g_parse_time);
#if defined(BRPC_PROFILE_H2)
bvar
::
ScopedTimer
<
bvar
::
Adder
<
int64_t
>
>
tm
(
g_parse_time
);
#endif
H2Context
*
ctx
=
static_cast
<
H2Context
*>
(
socket
->
parsing_context
());
H2Context
*
ctx
=
static_cast
<
H2Context
*>
(
socket
->
parsing_context
());
if
(
ctx
==
NULL
)
{
if
(
ctx
==
NULL
)
{
if
(
read_eof
||
source
->
empty
())
{
if
(
read_eof
||
source
->
empty
())
{
...
@@ -1060,21 +1108,19 @@ void H2Context::ClearAbandonedStreamsImpl() {
...
@@ -1060,21 +1108,19 @@ void H2Context::ClearAbandonedStreamsImpl() {
void
H2StreamContext
::
Init
(
H2Context
*
conn_ctx
,
int
stream_id
)
{
void
H2StreamContext
::
Init
(
H2Context
*
conn_ctx
,
int
stream_id
)
{
_conn_ctx
=
conn_ctx
;
_conn_ctx
=
conn_ctx
;
_remote_window_
size
.
store
(
conn_ctx
->
remote_settings
().
initial_window_size
,
_remote_window_
left
.
store
(
conn_ctx
->
remote_settings
().
initial_window_size
,
butil
::
memory_order_relaxed
);
butil
::
memory_order_relaxed
);
_local_window_size
.
store
(
conn_ctx
->
local_settings
().
initial_window_size
,
butil
::
memory_order_relaxed
);
header
().
_h2_stream_id
=
stream_id
;
header
().
_h2_stream_id
=
stream_id
;
}
}
H2StreamContext
::
H2StreamContext
(
H2Context
*
conn_ctx
,
int
stream_id
)
H2StreamContext
::
H2StreamContext
(
H2Context
*
conn_ctx
,
int
stream_id
)
:
_conn_ctx
(
conn_ctx
)
:
_conn_ctx
(
conn_ctx
)
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
,
_state
(
H2_STREAM_IDLE
)
,
_state
(
H2_STREAM_IDLE
)
#endif
#endif
,
_stream_ended
(
false
)
,
_stream_ended
(
false
)
,
_remote_window_
size
(
conn_ctx
->
remote_settings
().
initial_window_size
)
,
_remote_window_
left
(
conn_ctx
->
remote_settings
().
initial_window_size
)
,
_
local_window_size
(
conn_ctx
->
local_settings
().
initial_window_size
)
,
_
deferred_window_update
(
0
)
,
_correlation_id
(
INVALID_BTHREAD_ID
.
value
)
{
,
_correlation_id
(
INVALID_BTHREAD_ID
.
value
)
{
header
().
set_version
(
2
,
0
);
header
().
set_version
(
2
,
0
);
header
().
_h2_stream_id
=
stream_id
;
header
().
_h2_stream_id
=
stream_id
;
...
@@ -1083,7 +1129,7 @@ H2StreamContext::H2StreamContext(H2Context* conn_ctx, int stream_id)
...
@@ -1083,7 +1129,7 @@ H2StreamContext::H2StreamContext(H2Context* conn_ctx, int stream_id)
#endif
#endif
}
}
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
void
H2StreamContext
::
SetState
(
H2StreamState
state
)
{
void
H2StreamContext
::
SetState
(
H2StreamState
state
)
{
const
H2StreamState
old_state
=
_state
;
const
H2StreamState
old_state
=
_state
;
_state
=
state
;
_state
=
state
;
...
@@ -1187,7 +1233,8 @@ static void PackH2Message(butil::IOBuf* out,
...
@@ -1187,7 +1233,8 @@ static void PackH2Message(butil::IOBuf* out,
butil
::
IOBuf
&
headers
,
butil
::
IOBuf
&
headers
,
const
butil
::
IOBuf
&
data
,
const
butil
::
IOBuf
&
data
,
int
stream_id
,
int
stream_id
,
const
H2Settings
&
remote_settings
)
{
H2Context
*
conn_ctx
)
{
const
H2Settings
&
remote_settings
=
conn_ctx
->
remote_settings
();
char
headbuf
[
FRAME_HEAD_SIZE
];
char
headbuf
[
FRAME_HEAD_SIZE
];
H2FrameHead
headers_head
=
{
H2FrameHead
headers_head
=
{
(
uint32_t
)
headers
.
size
(),
H2_FRAME_HEADERS
,
0
,
stream_id
};
(
uint32_t
)
headers
.
size
(),
H2_FRAME_HEADERS
,
0
,
stream_id
};
...
@@ -1233,6 +1280,13 @@ static void PackH2Message(butil::IOBuf* out,
...
@@ -1233,6 +1280,13 @@ static void PackH2Message(butil::IOBuf* out,
it
.
append_and_forward
(
out
,
data_head
.
payload_size
);
it
.
append_and_forward
(
out
,
data_head
.
payload_size
);
}
}
}
}
const
int64_t
conn_wu
=
conn_ctx
->
ReleaseDeferredWindowUpdate
();
if
(
conn_wu
>
0
)
{
char
winbuf
[
FRAME_HEAD_SIZE
+
4
];
SerializeFrameHead
(
winbuf
,
4
,
H2_FRAME_WINDOW_UPDATE
,
0
,
0
);
SaveUint32
(
winbuf
+
FRAME_HEAD_SIZE
,
conn_wu
);
out
->
append
(
winbuf
,
sizeof
(
winbuf
));
}
}
}
H2UnsentRequest
*
H2UnsentRequest
::
New
(
Controller
*
c
)
{
H2UnsentRequest
*
H2UnsentRequest
::
New
(
Controller
*
c
)
{
...
@@ -1349,13 +1403,17 @@ void H2UnsentRequest::DestroyStreamUserData(SocketUniquePtr& sending_sock,
...
@@ -1349,13 +1403,17 @@ void H2UnsentRequest::DestroyStreamUserData(SocketUniquePtr& sending_sock,
}
}
}
}
// bvar::Adder<int64_t> g_append_request_time;
#if defined(BRPC_PROFILE_H2)
// bvar::PerSecond<bvar::Adder<int64_t> > g_append_request_time_per_second(
bvar
::
Adder
<
int64_t
>
g_append_request_time
;
// "h2_append_request_second", &g_append_request_time);
bvar
::
PerSecond
<
bvar
::
Adder
<
int64_t
>
>
g_append_request_time_per_second
(
"h2_append_request_second"
,
&
g_append_request_time
);
#endif
butil
::
Status
butil
::
Status
H2UnsentRequest
::
AppendAndDestroySelf
(
butil
::
IOBuf
*
out
,
Socket
*
socket
)
{
H2UnsentRequest
::
AppendAndDestroySelf
(
butil
::
IOBuf
*
out
,
Socket
*
socket
)
{
//bvar::ScopedTimer<bvar::Adder<int64_t> > tm(g_append_request_time);
#if defined(BRPC_PROFILE_H2)
bvar
::
ScopedTimer
<
bvar
::
Adder
<
int64_t
>
>
tm
(
g_append_request_time
);
#endif
RemoveRefOnQuit
deref_self
(
this
);
RemoveRefOnQuit
deref_self
(
this
);
if
(
socket
==
NULL
)
{
if
(
socket
==
NULL
)
{
return
butil
::
Status
::
OK
();
return
butil
::
Status
::
OK
();
...
@@ -1375,9 +1433,18 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
...
@@ -1375,9 +1433,18 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
// Append client connection preface
// Append client connection preface
out
->
append
(
H2_CONNECTION_PREFACE_PREFIX
,
out
->
append
(
H2_CONNECTION_PREFACE_PREFIX
,
H2_CONNECTION_PREFACE_PREFIX_SIZE
);
H2_CONNECTION_PREFACE_PREFIX_SIZE
);
char
headbuf
[
FRAME_HEAD_SIZE
];
SerializeFrameHead
(
headbuf
,
0
,
H2_FRAME_SETTINGS
,
0
,
0
);
char
settingsbuf
[
FRAME_HEAD_SIZE
+
H2Settings
::
MAX_BYTE_SIZE
];
out
->
append
(
headbuf
,
FRAME_HEAD_SIZE
);
const
size_t
nb
=
ctx
->
_unack_local_settings
.
SerializeTo
(
settingsbuf
+
FRAME_HEAD_SIZE
);
SerializeFrameHead
(
settingsbuf
,
nb
,
H2_FRAME_SETTINGS
,
0
,
0
);
out
->
append
(
settingsbuf
,
FRAME_HEAD_SIZE
+
nb
);
}
// FIXME(gejun): Replace EAGAIN
// TODO(zhujiashun): also check this in server push
if
(
ctx
->
VolatilePendingStreamSize
()
>
ctx
->
remote_settings
().
max_concurrent_streams
)
{
return
butil
::
Status
(
EAGAIN
,
"Pending Stream count exceeds max concurrent stream"
);
}
}
// Although the critical section looks huge, it should rarely be contended
// Although the critical section looks huge, it should rarely be contended
...
@@ -1387,11 +1454,6 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
...
@@ -1387,11 +1454,6 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
return
butil
::
Status
(
ECANCELED
,
"The RPC was already failed"
);
return
butil
::
Status
(
ECANCELED
,
"The RPC was already failed"
);
}
}
// TODO(zhujiashun): also check this in server push
if
(
ctx
->
StreamSize
()
>
ctx
->
remote_settings
().
max_concurrent_streams
)
{
return
butil
::
Status
(
EAGAIN
,
"Pending Stream count exceeds max concurrent stream"
);
}
const
int
id
=
ctx
->
AllocateClientStreamId
();
const
int
id
=
ctx
->
AllocateClientStreamId
();
if
(
id
<
0
)
{
if
(
id
<
0
)
{
// The RPC should be failed and retried.
// The RPC should be failed and retried.
...
@@ -1409,6 +1471,14 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
...
@@ -1409,6 +1471,14 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
}
}
_stream_id
=
sctx
->
stream_id
();
_stream_id
=
sctx
->
stream_id
();
// flow control
if
(
!
_cntl
->
request_attachment
().
empty
())
{
const
int64_t
data_size
=
_cntl
->
request_attachment
().
size
();
if
(
!
sctx
->
ConsumeWindowSize
(
data_size
))
{
return
butil
::
Status
(
EAGAIN
,
"remote_window_left is not enough, data_size=%"
PRId64
,
data_size
);
}
}
HPacker
&
hpacker
=
ctx
->
hpacker
();
HPacker
&
hpacker
=
ctx
->
hpacker
();
butil
::
IOBufAppender
appender
;
butil
::
IOBufAppender
appender
;
HPackOptions
options
;
HPackOptions
options
;
...
@@ -1427,21 +1497,7 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
...
@@ -1427,21 +1497,7 @@ H2UnsentRequest::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
}
}
butil
::
IOBuf
frag
;
butil
::
IOBuf
frag
;
appender
.
move_to
(
frag
);
appender
.
move_to
(
frag
);
PackH2Message
(
out
,
frag
,
_cntl
->
request_attachment
(),
_stream_id
,
ctx
);
// flow control
int64_t
s_win
=
sctx
->
_remote_window_size
.
load
(
butil
::
memory_order_relaxed
);
int64_t
c_win
=
ctx
->
_remote_conn_window_size
.
load
(
butil
::
memory_order_relaxed
);
const
int64_t
sz
=
_cntl
->
request_attachment
().
size
();
if
(
sz
>
s_win
||
sz
>
c_win
)
{
return
butil
::
Status
(
EAGAIN
,
"Remote window size is not enough(flow control)"
);
}
if
(
!
consume_window_size
(
&
sctx
->
_remote_window_size
,
sz
)
||
!
consume_window_size
(
&
ctx
->
_remote_conn_window_size
,
sz
))
{
return
butil
::
Status
(
EAGAIN
,
"Remote window size is not enough(flow control)"
);
}
PackH2Message
(
out
,
frag
,
_cntl
->
request_attachment
(),
_stream_id
,
ctx
->
remote_settings
());
return
butil
::
Status
::
OK
();
return
butil
::
Status
::
OK
();
}
}
...
@@ -1537,19 +1593,31 @@ void H2UnsentResponse::Destroy() {
...
@@ -1537,19 +1593,31 @@ void H2UnsentResponse::Destroy() {
free
(
this
);
free
(
this
);
}
}
// bvar::Adder<int64_t> g_append_response_time;
#if defined(BRPC_PROFILE_H2)
// bvar::PerSecond<bvar::Adder<int64_t> > g_append_response_time_per_second(
bvar
::
Adder
<
int64_t
>
g_append_response_time
;
// "h2_append_response_second", &g_append_response_time);
bvar
::
PerSecond
<
bvar
::
Adder
<
int64_t
>
>
g_append_response_time_per_second
(
"h2_append_response_second"
,
&
g_append_response_time
);
#endif
butil
::
Status
butil
::
Status
H2UnsentResponse
::
AppendAndDestroySelf
(
butil
::
IOBuf
*
out
,
Socket
*
socket
)
{
H2UnsentResponse
::
AppendAndDestroySelf
(
butil
::
IOBuf
*
out
,
Socket
*
socket
)
{
//bvar::ScopedTimer<bvar::Adder<int64_t> > tm(g_append_response_time);
#if defined(BRPC_PROFILE_H2)
bvar
::
ScopedTimer
<
bvar
::
Adder
<
int64_t
>
>
tm
(
g_append_response_time
);
#endif
DestroyingPtr
<
H2UnsentResponse
>
destroy_self
(
this
);
DestroyingPtr
<
H2UnsentResponse
>
destroy_self
(
this
);
if
(
socket
==
NULL
)
{
if
(
socket
==
NULL
)
{
return
butil
::
Status
::
OK
();
return
butil
::
Status
::
OK
();
}
}
H2Context
*
ctx
=
static_cast
<
H2Context
*>
(
socket
->
parsing_context
());
H2Context
*
ctx
=
static_cast
<
H2Context
*>
(
socket
->
parsing_context
());
// flow control
// NOTE: Currently the stream context is definitely removed and updating
// window size is useless, however it's not true when progressive request
// is supported.
if
(
!
MinusWindowSize
(
&
ctx
->
_remote_window_left
,
_data
.
size
()))
{
return
butil
::
Status
(
EAGAIN
,
"Remote window size is not enough"
);
}
HPacker
&
hpacker
=
ctx
->
hpacker
();
HPacker
&
hpacker
=
ctx
->
hpacker
();
butil
::
IOBufAppender
appender
;
butil
::
IOBufAppender
appender
;
HPackOptions
options
;
HPackOptions
options
;
...
@@ -1569,14 +1637,7 @@ H2UnsentResponse::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
...
@@ -1569,14 +1637,7 @@ H2UnsentResponse::AppendAndDestroySelf(butil::IOBuf* out, Socket* socket) {
butil
::
IOBuf
frag
;
butil
::
IOBuf
frag
;
appender
.
move_to
(
frag
);
appender
.
move_to
(
frag
);
// flow control
PackH2Message
(
out
,
frag
,
_data
,
_stream_id
,
ctx
);
int64_t
c_win
=
ctx
->
_remote_conn_window_size
.
load
(
butil
::
memory_order_relaxed
);
const
int64_t
sz
=
_data
.
size
();
if
((
sz
>
c_win
)
||
!
consume_window_size
(
&
ctx
->
_remote_conn_window_size
,
sz
))
{
return
butil
::
Status
(
EAGAIN
,
"Remote window size is not enough(flow control)"
);
}
PackH2Message
(
out
,
frag
,
_data
,
_stream_id
,
ctx
->
remote_settings
());
return
butil
::
Status
::
OK
();
return
butil
::
Status
::
OK
();
}
}
...
...
src/brpc/policy/http2_rpc_protocol.h
View file @
513ed819
...
@@ -24,7 +24,10 @@
...
@@ -24,7 +24,10 @@
#include "brpc/details/hpack.h"
#include "brpc/details/hpack.h"
#include "brpc/stream_creator.h"
#include "brpc/stream_creator.h"
#include "brpc/controller.h"
#include "brpc/controller.h"
#ifndef NDEBUG
#include "bvar/bvar.h"
#include "bvar/bvar.h"
#endif
namespace
brpc
{
namespace
brpc
{
...
@@ -159,8 +162,8 @@ public:
...
@@ -159,8 +162,8 @@ public:
void
Destroy
();
void
Destroy
();
void
Describe
(
butil
::
IOBuf
*
)
const
;
void
Describe
(
butil
::
IOBuf
*
)
const
;
// @SocketMessage
// @SocketMessage
butil
::
Status
AppendAndDestroySelf
(
butil
::
IOBuf
*
out
,
Socket
*
);
butil
::
Status
AppendAndDestroySelf
(
butil
::
IOBuf
*
out
,
Socket
*
)
override
;
size_t
EstimatedByteSize
();
size_t
EstimatedByteSize
()
override
;
private
:
private
:
std
::
string
&
push
(
const
std
::
string
&
name
)
std
::
string
&
push
(
const
std
::
string
&
name
)
...
@@ -214,19 +217,28 @@ public:
...
@@ -214,19 +217,28 @@ public:
size_t
parsed_length
()
const
{
return
this
->
_parsed_length
;
}
size_t
parsed_length
()
const
{
return
this
->
_parsed_length
;
}
int
stream_id
()
const
{
return
header
().
h2_stream_id
();
}
int
stream_id
()
const
{
return
header
().
h2_stream_id
();
}
#ifdef HAS_H2_STREAM_STATE
int64_t
ReleaseDeferredWindowUpdate
()
{
if
(
_deferred_window_update
.
load
(
butil
::
memory_order_relaxed
)
==
0
)
{
return
0
;
}
return
_deferred_window_update
.
exchange
(
0
,
butil
::
memory_order_relaxed
);
}
bool
ConsumeWindowSize
(
int64_t
size
);
#if defined(BRPC_H2_STREAM_STATE)
H2StreamState
state
()
const
{
return
_state
;
}
H2StreamState
state
()
const
{
return
_state
;
}
void
SetState
(
H2StreamState
state
);
void
SetState
(
H2StreamState
state
);
#endif
#endif
friend
class
H2Context
;
friend
class
H2Context
;
H2Context
*
_conn_ctx
;
H2Context
*
_conn_ctx
;
#if
def HAS_H2_STREAM_STATE
#if
defined(BRPC_H2_STREAM_STATE)
H2StreamState
_state
;
H2StreamState
_state
;
#endif
#endif
bool
_stream_ended
;
bool
_stream_ended
;
butil
::
atomic
<
int64_t
>
_remote_window_
size
;
butil
::
atomic
<
int64_t
>
_remote_window_
left
;
butil
::
atomic
<
int64_t
>
_
local_window_siz
e
;
butil
::
atomic
<
int64_t
>
_
deferred_window_updat
e
;
uint64_t
_correlation_id
;
uint64_t
_correlation_id
;
butil
::
IOBuf
_remaining_header_fragment
;
butil
::
IOBuf
_remaining_header_fragment
;
};
};
...
@@ -250,7 +262,6 @@ protected:
...
@@ -250,7 +262,6 @@ protected:
};
};
}
// namespace policy
}
// namespace policy
}
// namespace brpc
}
// namespace brpc
#endif // BAIDU_RPC_POLICY_HTTP2_RPC_PROTOCOL_H
#endif // BAIDU_RPC_POLICY_HTTP2_RPC_PROTOCOL_H
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