Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
9d4e8eeb
Commit
9d4e8eeb
authored
Sep 11, 2016
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Simplify code
Move DATA frame handling code to switch-case of frame type.
parent
8099dd95
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
320 additions
and
356 deletions
+320
-356
lib/nghttp2_session.c
lib/nghttp2_session.c
+320
-356
No files found.
lib/nghttp2_session.c
View file @
9d4e8eeb
...
...
@@ -816,99 +816,96 @@ int nghttp2_session_add_item(nghttp2_session *session,
frame
=
&
item
->
frame
;
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
if
(
frame
->
hd
.
type
!=
NGHTTP2_DATA
)
{
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_DATA
:
if
(
!
stream
)
{
return
NGHTTP2_ERR_STREAM_CLOSED
;
}
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_HEADERS
:
/* We push request HEADERS and push response HEADERS to
dedicated queue because their transmission is affected by
SETTINGS_MAX_CONCURRENT_STREAMS */
/* TODO If 2 HEADERS are submitted for reserved stream, then
both of them are queued into ob_syn, which is not
desirable. */
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
||
(
stream
&&
stream
->
state
==
NGHTTP2_STREAM_RESERVED
))
{
nghttp2_outbound_queue_push
(
&
session
->
ob_syn
,
item
);
item
->
queued
=
1
;
break
;
}
if
(
stream
->
item
)
{
return
NGHTTP2_ERR_DATA_EXIST
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
break
;
case
NGHTTP2_SETTINGS
:
case
NGHTTP2_PING
:
nghttp2_outbound_queue_push
(
&
session
->
ob_urgent
,
item
);
item
->
queued
=
1
;
break
;
case
NGHTTP2_RST_STREAM
:
if
(
stream
)
{
stream
->
state
=
NGHTTP2_STREAM_CLOSING
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
break
;
case
NGHTTP2_PUSH_PROMISE
:
{
nghttp2_headers_aux_data
*
aux_data
;
nghttp2_priority_spec
pri_spec
;
rv
=
nghttp2_stream_attach_item
(
stream
,
item
);
aux_data
=
&
item
->
aux_data
.
headers
;
if
(
rv
!=
0
)
{
return
rv
;
}
if
(
!
stream
)
{
return
NGHTTP2_ERR_STREAM_CLOSED
;
}
return
0
;
case
NGHTTP2_HEADERS
:
/* We push request HEADERS and push response HEADERS to
dedicated queue because their transmission is affected by
SETTINGS_MAX_CONCURRENT_STREAMS */
/* TODO If 2 HEADERS are submitted for reserved stream, then
both of them are queued into ob_syn, which is not
desirable. */
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
||
(
stream
&&
stream
->
state
==
NGHTTP2_STREAM_RESERVED
))
{
nghttp2_outbound_queue_push
(
&
session
->
ob_syn
,
item
);
item
->
queued
=
1
;
return
0
;
;
}
nghttp2_priority_spec_init
(
&
pri_spec
,
stream
->
stream_id
,
NGHTTP2_DEFAULT_WEIGHT
,
0
);
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
return
0
;
case
NGHTTP2_SETTINGS
:
case
NGHTTP2_PING
:
nghttp2_outbound_queue_push
(
&
session
->
ob_urgent
,
item
);
item
->
queued
=
1
;
return
0
;
case
NGHTTP2_RST_STREAM
:
if
(
stream
)
{
stream
->
state
=
NGHTTP2_STREAM_CLOSING
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
return
0
;
case
NGHTTP2_PUSH_PROMISE
:
{
nghttp2_headers_aux_data
*
aux_data
;
nghttp2_priority_spec
pri_spec
;
if
(
!
nghttp2_session_open_stream
(
session
,
frame
->
push_promise
.
promised_stream_id
,
NGHTTP2_STREAM_FLAG_NONE
,
&
pri_spec
,
NGHTTP2_STREAM_RESERVED
,
aux_data
->
stream_user_data
))
{
return
NGHTTP2_ERR_NOMEM
;
}
aux_data
=
&
item
->
aux_data
.
headers
;
/* We don't have to call nghttp2_session_adjust_closed_stream()
here, since stream->stream_id is local stream_id, and it does
not affect closed stream count. */
if
(
!
stream
)
{
return
NGHTTP2_ERR_STREAM_CLOSED
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
nghttp2_priority_spec_init
(
&
pri_spec
,
stream
->
stream_id
,
NGHTTP2_DEFAULT_WEIGHT
,
0
)
;
break
;
}
case
NGHTTP2_WINDOW_UPDATE
:
if
(
stream
)
{
stream
->
window_update_queued
=
1
;
}
else
if
(
frame
->
hd
.
stream_id
==
0
)
{
session
->
window_update_queued
=
1
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
break
;
default:
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
if
(
!
nghttp2_session_open_stream
(
session
,
frame
->
push_promise
.
promised_stream_id
,
NGHTTP2_STREAM_FLAG_NONE
,
&
pri_spec
,
NGHTTP2_STREAM_RESERVED
,
aux_data
->
stream_user_data
))
{
return
NGHTTP2_ERR_NOMEM
;
}
return
0
;
}
/* We don't have to call nghttp2_session_adjust_closed_stream()
here, since stream->stream_id is local stream_id, and it does
not affect closed stream count. */
if
(
!
stream
)
{
return
NGHTTP2_ERR_STREAM_CLOSED
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
if
(
stream
->
item
)
{
return
NGHTTP2_ERR_DATA_EXIST
;
return
0
;
}
rv
=
nghttp2_stream_attach_item
(
stream
,
item
);
if
(
rv
!=
0
)
{
return
rv
;
case
NGHTTP2_WINDOW_UPDATE
:
if
(
stream
)
{
stream
->
window_update_queued
=
1
;
}
else
if
(
frame
->
hd
.
stream_id
==
0
)
{
session
->
window_update_queued
=
1
;
}
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
return
0
;
default:
nghttp2_outbound_queue_push
(
&
session
->
ob_reg
,
item
);
item
->
queued
=
1
;
return
0
;
}
return
0
;
}
int
nghttp2_session_add_rst_stream
(
nghttp2_session
*
session
,
int32_t
stream_id
,
...
...
@@ -1941,276 +1938,8 @@ static int session_prep_frame(nghttp2_session *session,
mem
=
&
session
->
mem
;
frame
=
&
item
->
frame
;
if
(
frame
->
hd
.
type
!=
NGHTTP2_DATA
)
{
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_HEADERS
:
{
nghttp2_headers_aux_data
*
aux_data
;
size_t
estimated_payloadlen
;
aux_data
=
&
item
->
aux_data
.
headers
;
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
)
{
/* initial HEADERS, which opens stream */
nghttp2_stream
*
stream
;
stream
=
nghttp2_session_open_stream
(
session
,
frame
->
hd
.
stream_id
,
NGHTTP2_STREAM_FLAG_NONE
,
&
frame
->
headers
.
pri_spec
,
NGHTTP2_STREAM_INITIAL
,
aux_data
->
stream_user_data
);
if
(
stream
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
/* We don't call nghttp2_session_adjust_closed_stream() here,
since we don't keep closed stream in client side */
estimated_payloadlen
=
session_estimate_headers_payload
(
session
,
frame
->
headers
.
nva
,
frame
->
headers
.
nvlen
,
NGHTTP2_PRIORITY_SPECLEN
);
if
(
estimated_payloadlen
>
session
->
max_send_header_block_length
)
{
return
NGHTTP2_ERR_FRAME_SIZE_ERROR
;
}
rv
=
session_predicate_request_headers_send
(
session
,
item
);
if
(
rv
!=
0
)
{
return
rv
;
}
if
(
session_enforce_http_messaging
(
session
))
{
nghttp2_http_record_request_method
(
stream
,
frame
);
}
}
else
{
nghttp2_stream
*
stream
;
estimated_payloadlen
=
session_estimate_headers_payload
(
session
,
frame
->
headers
.
nva
,
frame
->
headers
.
nvlen
,
NGHTTP2_PRIORITY_SPECLEN
);
if
(
estimated_payloadlen
>
session
->
max_send_header_block_length
)
{
return
NGHTTP2_ERR_FRAME_SIZE_ERROR
;
}
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
if
(
stream
&&
stream
->
state
==
NGHTTP2_STREAM_RESERVED
)
{
rv
=
session_predicate_push_response_headers_send
(
session
,
stream
);
if
(
rv
==
0
)
{
frame
->
headers
.
cat
=
NGHTTP2_HCAT_PUSH_RESPONSE
;
if
(
aux_data
->
stream_user_data
)
{
stream
->
stream_user_data
=
aux_data
->
stream_user_data
;
}
}
}
else
if
(
session_predicate_response_headers_send
(
session
,
stream
)
==
0
)
{
frame
->
headers
.
cat
=
NGHTTP2_HCAT_RESPONSE
;
rv
=
0
;
}
else
{
frame
->
headers
.
cat
=
NGHTTP2_HCAT_HEADERS
;
rv
=
session_predicate_headers_send
(
session
,
stream
);
}
if
(
rv
!=
0
)
{
// If stream was already closed, nghttp2_session_get_stream()
// returns NULL, but item is still attached to the stream.
// Search stream including closed again.
stream
=
nghttp2_session_get_stream_raw
(
session
,
frame
->
hd
.
stream_id
);
if
(
stream
&&
stream
->
item
==
item
)
{
int
rv2
;
rv2
=
nghttp2_stream_detach_item
(
stream
);
if
(
nghttp2_is_fatal
(
rv2
))
{
return
rv2
;
}
}
return
rv
;
}
}
rv
=
nghttp2_frame_pack_headers
(
&
session
->
aob
.
framebufs
,
&
frame
->
headers
,
&
session
->
hd_deflater
);
if
(
rv
!=
0
)
{
return
rv
;
}
DEBUGF
(
fprintf
(
stderr
,
"send: before padding, HEADERS serialized in %zd bytes
\n
"
,
nghttp2_bufs_len
(
&
session
->
aob
.
framebufs
)));
rv
=
session_headers_add_pad
(
session
,
frame
);
if
(
rv
!=
0
)
{
return
rv
;
}
DEBUGF
(
fprintf
(
stderr
,
"send: HEADERS finally serialized in %zd bytes
\n
"
,
nghttp2_bufs_len
(
&
session
->
aob
.
framebufs
)));
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
)
{
assert
(
session
->
last_sent_stream_id
<
frame
->
hd
.
stream_id
);
session
->
last_sent_stream_id
=
frame
->
hd
.
stream_id
;
}
break
;
}
case
NGHTTP2_PRIORITY
:
{
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
/* PRIORITY frame can be sent at any time and to any stream
ID. */
nghttp2_frame_pack_priority
(
&
session
->
aob
.
framebufs
,
&
frame
->
priority
);
/* Peer can send PRIORITY frame against idle stream to create
"anchor" in dependency tree. Only client can do this in
nghttp2. In nghttp2, only server retains non-active (closed
or idle) streams in memory, so we don't open stream here. */
break
;
}
case
NGHTTP2_RST_STREAM
:
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
nghttp2_frame_pack_rst_stream
(
&
session
->
aob
.
framebufs
,
&
frame
->
rst_stream
);
break
;
case
NGHTTP2_SETTINGS
:
{
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
assert
(
session
->
obq_flood_counter_
>
0
);
--
session
->
obq_flood_counter_
;
/* When session is about to close, don't send SETTINGS ACK.
We are required to send SETTINGS without ACK though; for
example, we have to send SETTINGS as a part of connection
preface. */
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
}
rv
=
nghttp2_frame_pack_settings
(
&
session
->
aob
.
framebufs
,
&
frame
->
settings
);
if
(
rv
!=
0
)
{
return
rv
;
}
break
;
}
case
NGHTTP2_PUSH_PROMISE
:
{
nghttp2_stream
*
stream
;
size_t
estimated_payloadlen
;
estimated_payloadlen
=
session_estimate_headers_payload
(
session
,
frame
->
push_promise
.
nva
,
frame
->
push_promise
.
nvlen
,
0
);
if
(
estimated_payloadlen
>
session
->
max_send_header_block_length
)
{
return
NGHTTP2_ERR_FRAME_SIZE_ERROR
;
}
/* stream could be NULL if associated stream was already
closed. */
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
/* predicte should fail if stream is NULL. */
rv
=
session_predicate_push_promise_send
(
session
,
stream
);
if
(
rv
!=
0
)
{
return
rv
;
}
assert
(
stream
);
rv
=
nghttp2_frame_pack_push_promise
(
&
session
->
aob
.
framebufs
,
&
frame
->
push_promise
,
&
session
->
hd_deflater
);
if
(
rv
!=
0
)
{
return
rv
;
}
rv
=
session_headers_add_pad
(
session
,
frame
);
if
(
rv
!=
0
)
{
return
rv
;
}
assert
(
session
->
last_sent_stream_id
+
2
<=
frame
->
push_promise
.
promised_stream_id
);
session
->
last_sent_stream_id
=
frame
->
push_promise
.
promised_stream_id
;
break
;
}
case
NGHTTP2_PING
:
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
assert
(
session
->
obq_flood_counter_
>
0
);
--
session
->
obq_flood_counter_
;
}
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
nghttp2_frame_pack_ping
(
&
session
->
aob
.
framebufs
,
&
frame
->
ping
);
break
;
case
NGHTTP2_GOAWAY
:
rv
=
nghttp2_frame_pack_goaway
(
&
session
->
aob
.
framebufs
,
&
frame
->
goaway
);
if
(
rv
!=
0
)
{
return
rv
;
}
session
->
local_last_stream_id
=
frame
->
goaway
.
last_stream_id
;
break
;
case
NGHTTP2_WINDOW_UPDATE
:
rv
=
session_predicate_window_update_send
(
session
,
frame
->
hd
.
stream_id
);
if
(
rv
!=
0
)
{
return
rv
;
}
nghttp2_frame_pack_window_update
(
&
session
->
aob
.
framebufs
,
&
frame
->
window_update
);
break
;
case
NGHTTP2_CONTINUATION
:
/* We never handle CONTINUATION here. */
assert
(
0
);
break
;
default:
{
nghttp2_ext_aux_data
*
aux_data
;
/* extension frame */
aux_data
=
&
item
->
aux_data
.
ext
;
if
(
aux_data
->
builtin
==
0
)
{
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
rv
=
session_pack_extension
(
session
,
&
session
->
aob
.
framebufs
,
frame
);
if
(
rv
!=
0
)
{
return
rv
;
}
break
;
}
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_ALTSVC
:
rv
=
session_predicate_altsvc_send
(
session
,
frame
->
hd
.
stream_id
);
if
(
rv
!=
0
)
{
return
rv
;
}
nghttp2_frame_pack_altsvc
(
&
session
->
aob
.
framebufs
,
&
frame
->
ext
);
break
;
default:
/* Unreachable here */
assert
(
0
);
break
;
}
break
;
}
}
return
0
;
}
else
{
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_DATA
:
{
size_t
next_readmax
;
nghttp2_stream
*
stream
;
...
...
@@ -2304,6 +2033,249 @@ static int session_prep_frame(nghttp2_session *session,
}
return
0
;
}
case
NGHTTP2_HEADERS
:
{
nghttp2_headers_aux_data
*
aux_data
;
size_t
estimated_payloadlen
;
aux_data
=
&
item
->
aux_data
.
headers
;
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
)
{
/* initial HEADERS, which opens stream */
nghttp2_stream
*
stream
;
stream
=
nghttp2_session_open_stream
(
session
,
frame
->
hd
.
stream_id
,
NGHTTP2_STREAM_FLAG_NONE
,
&
frame
->
headers
.
pri_spec
,
NGHTTP2_STREAM_INITIAL
,
aux_data
->
stream_user_data
);
if
(
stream
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
/* We don't call nghttp2_session_adjust_closed_stream() here,
since we don't keep closed stream in client side */
estimated_payloadlen
=
session_estimate_headers_payload
(
session
,
frame
->
headers
.
nva
,
frame
->
headers
.
nvlen
,
NGHTTP2_PRIORITY_SPECLEN
);
if
(
estimated_payloadlen
>
session
->
max_send_header_block_length
)
{
return
NGHTTP2_ERR_FRAME_SIZE_ERROR
;
}
rv
=
session_predicate_request_headers_send
(
session
,
item
);
if
(
rv
!=
0
)
{
return
rv
;
}
if
(
session_enforce_http_messaging
(
session
))
{
nghttp2_http_record_request_method
(
stream
,
frame
);
}
}
else
{
nghttp2_stream
*
stream
;
estimated_payloadlen
=
session_estimate_headers_payload
(
session
,
frame
->
headers
.
nva
,
frame
->
headers
.
nvlen
,
NGHTTP2_PRIORITY_SPECLEN
);
if
(
estimated_payloadlen
>
session
->
max_send_header_block_length
)
{
return
NGHTTP2_ERR_FRAME_SIZE_ERROR
;
}
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
if
(
stream
&&
stream
->
state
==
NGHTTP2_STREAM_RESERVED
)
{
rv
=
session_predicate_push_response_headers_send
(
session
,
stream
);
if
(
rv
==
0
)
{
frame
->
headers
.
cat
=
NGHTTP2_HCAT_PUSH_RESPONSE
;
if
(
aux_data
->
stream_user_data
)
{
stream
->
stream_user_data
=
aux_data
->
stream_user_data
;
}
}
}
else
if
(
session_predicate_response_headers_send
(
session
,
stream
)
==
0
)
{
frame
->
headers
.
cat
=
NGHTTP2_HCAT_RESPONSE
;
rv
=
0
;
}
else
{
frame
->
headers
.
cat
=
NGHTTP2_HCAT_HEADERS
;
rv
=
session_predicate_headers_send
(
session
,
stream
);
}
if
(
rv
!=
0
)
{
return
rv
;
}
}
rv
=
nghttp2_frame_pack_headers
(
&
session
->
aob
.
framebufs
,
&
frame
->
headers
,
&
session
->
hd_deflater
);
if
(
rv
!=
0
)
{
return
rv
;
}
DEBUGF
(
fprintf
(
stderr
,
"send: before padding, HEADERS serialized in %zd bytes
\n
"
,
nghttp2_bufs_len
(
&
session
->
aob
.
framebufs
)));
rv
=
session_headers_add_pad
(
session
,
frame
);
if
(
rv
!=
0
)
{
return
rv
;
}
DEBUGF
(
fprintf
(
stderr
,
"send: HEADERS finally serialized in %zd bytes
\n
"
,
nghttp2_bufs_len
(
&
session
->
aob
.
framebufs
)));
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
)
{
assert
(
session
->
last_sent_stream_id
<
frame
->
hd
.
stream_id
);
session
->
last_sent_stream_id
=
frame
->
hd
.
stream_id
;
}
return
0
;
}
case
NGHTTP2_PRIORITY
:
{
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
/* PRIORITY frame can be sent at any time and to any stream
ID. */
nghttp2_frame_pack_priority
(
&
session
->
aob
.
framebufs
,
&
frame
->
priority
);
/* Peer can send PRIORITY frame against idle stream to create
"anchor" in dependency tree. Only client can do this in
nghttp2. In nghttp2, only server retains non-active (closed
or idle) streams in memory, so we don't open stream here. */
return
0
;
}
case
NGHTTP2_RST_STREAM
:
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
nghttp2_frame_pack_rst_stream
(
&
session
->
aob
.
framebufs
,
&
frame
->
rst_stream
);
return
0
;
case
NGHTTP2_SETTINGS
:
{
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
assert
(
session
->
obq_flood_counter_
>
0
);
--
session
->
obq_flood_counter_
;
/* When session is about to close, don't send SETTINGS ACK.
We are required to send SETTINGS without ACK though; for
example, we have to send SETTINGS as a part of connection
preface. */
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
}
rv
=
nghttp2_frame_pack_settings
(
&
session
->
aob
.
framebufs
,
&
frame
->
settings
);
if
(
rv
!=
0
)
{
return
rv
;
}
return
0
;
}
case
NGHTTP2_PUSH_PROMISE
:
{
nghttp2_stream
*
stream
;
size_t
estimated_payloadlen
;
estimated_payloadlen
=
session_estimate_headers_payload
(
session
,
frame
->
push_promise
.
nva
,
frame
->
push_promise
.
nvlen
,
0
);
if
(
estimated_payloadlen
>
session
->
max_send_header_block_length
)
{
return
NGHTTP2_ERR_FRAME_SIZE_ERROR
;
}
/* stream could be NULL if associated stream was already
closed. */
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
/* predicte should fail if stream is NULL. */
rv
=
session_predicate_push_promise_send
(
session
,
stream
);
if
(
rv
!=
0
)
{
return
rv
;
}
assert
(
stream
);
rv
=
nghttp2_frame_pack_push_promise
(
&
session
->
aob
.
framebufs
,
&
frame
->
push_promise
,
&
session
->
hd_deflater
);
if
(
rv
!=
0
)
{
return
rv
;
}
rv
=
session_headers_add_pad
(
session
,
frame
);
if
(
rv
!=
0
)
{
return
rv
;
}
assert
(
session
->
last_sent_stream_id
+
2
<=
frame
->
push_promise
.
promised_stream_id
);
session
->
last_sent_stream_id
=
frame
->
push_promise
.
promised_stream_id
;
return
0
;
}
case
NGHTTP2_PING
:
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
assert
(
session
->
obq_flood_counter_
>
0
);
--
session
->
obq_flood_counter_
;
}
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
nghttp2_frame_pack_ping
(
&
session
->
aob
.
framebufs
,
&
frame
->
ping
);
return
0
;
case
NGHTTP2_GOAWAY
:
rv
=
nghttp2_frame_pack_goaway
(
&
session
->
aob
.
framebufs
,
&
frame
->
goaway
);
if
(
rv
!=
0
)
{
return
rv
;
}
session
->
local_last_stream_id
=
frame
->
goaway
.
last_stream_id
;
return
0
;
case
NGHTTP2_WINDOW_UPDATE
:
rv
=
session_predicate_window_update_send
(
session
,
frame
->
hd
.
stream_id
);
if
(
rv
!=
0
)
{
return
rv
;
}
nghttp2_frame_pack_window_update
(
&
session
->
aob
.
framebufs
,
&
frame
->
window_update
);
return
0
;
case
NGHTTP2_CONTINUATION
:
/* We never handle CONTINUATION here. */
assert
(
0
);
return
0
;
default:
{
nghttp2_ext_aux_data
*
aux_data
;
/* extension frame */
aux_data
=
&
item
->
aux_data
.
ext
;
if
(
aux_data
->
builtin
==
0
)
{
if
(
session_is_closing
(
session
))
{
return
NGHTTP2_ERR_SESSION_CLOSING
;
}
return
session_pack_extension
(
session
,
&
session
->
aob
.
framebufs
,
frame
);
}
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_ALTSVC
:
rv
=
session_predicate_altsvc_send
(
session
,
frame
->
hd
.
stream_id
);
if
(
rv
!=
0
)
{
return
rv
;
}
nghttp2_frame_pack_altsvc
(
&
session
->
aob
.
framebufs
,
&
frame
->
ext
);
return
0
;
default:
/* Unreachable here */
assert
(
0
);
return
0
;
}
}
}
}
nghttp2_outbound_item
*
...
...
@@ -2538,14 +2510,6 @@ static int session_after_frame_sent1(nghttp2_session *session) {
break
;
}
if
(
stream
->
item
==
item
)
{
rv
=
nghttp2_stream_detach_item
(
stream
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
}
switch
(
frame
->
headers
.
cat
)
{
case
NGHTTP2_HCAT_REQUEST
:
{
stream
->
state
=
NGHTTP2_STREAM_OPENING
;
...
...
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