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
795ee8c2
Commit
795ee8c2
authored
Apr 03, 2016
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
altsvc: Receive ALTSVC frame
parent
efbd48b1
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
271 additions
and
17 deletions
+271
-17
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+21
-1
lib/nghttp2_frame.c
lib/nghttp2_frame.c
+19
-1
lib/nghttp2_frame.h
lib/nghttp2_frame.h
+24
-1
lib/nghttp2_option.c
lib/nghttp2_option.c
+15
-2
lib/nghttp2_option.h
lib/nghttp2_option.h
+6
-1
lib/nghttp2_outbound_item.c
lib/nghttp2_outbound_item.c
+2
-0
lib/nghttp2_session.c
lib/nghttp2_session.c
+167
-11
lib/nghttp2_session.h
lib/nghttp2_session.h
+15
-0
lib/nghttp2_submit.c
lib/nghttp2_submit.c
+1
-0
src/nghttp.cc
src/nghttp.cc
+1
-0
No files found.
lib/includes/nghttp2/nghttp2.h
View file @
795ee8c2
...
...
@@ -2377,6 +2377,26 @@ NGHTTP2_EXTERN void
nghttp2_option_set_user_recv_extension_type
(
nghttp2_option
*
option
,
uint8_t
type
);
/**
* @ function
*
* Sets extension frame type the application is willing to receive
* using builtin handler. The |type| is the extension frame type to
* receive, and must be strictly greater than 0x9. Otherwise, this
* function does nothing. The application can call this function
* multiple times to set more than one frame type to receive. The
* application does not have to call this function if it just sends
* extension frames.
*
* If same frame type is passed to both
* `nghttp2_option_set_builtin_recv_extension_type()` and
* `nghttp2_option_set_user_recv_extension_type()`, the latter takes
* precedence.
*/
NGHTTP2_EXTERN
void
nghttp2_option_set_builtin_recv_extension_type
(
nghttp2_option
*
option
,
uint8_t
type
);
/**
* @function
*
...
...
@@ -4123,7 +4143,7 @@ NGHTTP2_EXTERN int nghttp2_submit_extension(nghttp2_session *session,
* The payload of ALTSVC frame. ALTSVC frame is one of extension
* frame. If this frame is received, and
* `nghttp2_option_set_user_recv_extension_type()` is not set, and
* `nghttp2_option_set_recv_extension_type()` is set for
* `nghttp2_option_set_
builtin_
recv_extension_type()` is set for
* :enum:`NGHTTP2_ALTSVC`, ``nghttp2_extension.payload`` will point to
* this struct.
*
...
...
lib/nghttp2_frame.c
View file @
795ee8c2
...
...
@@ -215,7 +215,6 @@ void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
/* We use the same buffer for altsvc->origin and
altsvc->field_value. */
nghttp2_mem_free
(
mem
,
altsvc
->
origin
);
nghttp2_mem_free
(
mem
,
altsvc
);
}
size_t
nghttp2_frame_priority_len
(
uint8_t
flags
)
{
...
...
@@ -723,6 +722,25 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
return
0
;
}
void
nghttp2_frame_unpack_altsvc_payload
(
nghttp2_extension
*
frame
,
size_t
origin_len
,
uint8_t
*
payload
,
size_t
payloadlen
)
{
nghttp2_ext_altsvc
*
altsvc
;
uint8_t
*
p
;
altsvc
=
frame
->
payload
;
p
=
payload
;
altsvc
->
origin
=
p
;
p
+=
origin_len
;
altsvc
->
origin_len
=
origin_len
;
altsvc
->
field_value
=
p
;
altsvc
->
field_value_len
=
(
size_t
)(
payload
+
payloadlen
-
p
);
}
nghttp2_settings_entry
*
nghttp2_frame_iv_copy
(
const
nghttp2_settings_entry
*
iv
,
size_t
niv
,
nghttp2_mem
*
mem
)
{
nghttp2_settings_entry
*
iv_copy
;
...
...
lib/nghttp2_frame.h
View file @
795ee8c2
...
...
@@ -72,7 +72,7 @@
#define NGHTTP2_MAX_PADLEN 256
/* Union of extension frame payload */
typedef
union
{
int
dummy
;
}
nghttp2_ext_frame_payload
;
typedef
union
{
nghttp2_ext_altsvc
altsvc
;
}
nghttp2_ext_frame_payload
;
void
nghttp2_frame_pack_frame_hd
(
uint8_t
*
buf
,
const
nghttp2_frame_hd
*
hd
);
...
...
@@ -378,6 +378,16 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
*/
int
nghttp2_frame_pack_altsvc
(
nghttp2_bufs
*
bufs
,
nghttp2_extension
*
ext
);
/*
* Unpacks ALTSVC wire format into |frame|. The |payload| of
* |payloadlen| bytes contains frame payload. This function assumes
* that frame->payload points to the nghttp2_ext_altsvc object.
*
* This function always succeeds and returns 0.
*/
void
nghttp2_frame_unpack_altsvc_payload
(
nghttp2_extension
*
frame
,
size_t
origin_len
,
uint8_t
*
payload
,
size_t
payloadlen
);
/*
* Initializes HEADERS frame |frame| with given values. |frame| takes
* ownership of |nva|, so caller must not free it. If |stream_id| is
...
...
@@ -456,10 +466,23 @@ void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
void
nghttp2_frame_extension_free
(
nghttp2_extension
*
frame
);
/*
* Initializes ALTSVC frame |frame| with given values. This function
* assumes that frame->payload points to nghttp2_ext_altsvc object.
* Also |origin| and |field_value| are allocated in single buffer,
* starting |origin|. On success, this function takes ownership of
* |origin|, so caller must not free it.
*/
void
nghttp2_frame_altsvc_init
(
nghttp2_extension
*
frame
,
int32_t
stream_id
,
uint8_t
*
origin
,
size_t
origin_len
,
uint8_t
*
field_value
,
size_t
field_value_len
);
/*
* Frees up resources under |frame|. This function does not free
* nghttp2_ext_altsvc object pointed by frame->payload. This function
* only frees origin pointed by nghttp2_ext_altsvc.origin. Therefore,
* other fields must be allocated in the same buffer with origin.
*/
void
nghttp2_frame_altsvc_free
(
nghttp2_extension
*
frame
,
nghttp2_mem
*
mem
);
/*
...
...
lib/nghttp2_option.c
View file @
795ee8c2
...
...
@@ -63,6 +63,10 @@ void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
option
->
max_reserved_remote_streams
=
val
;
}
static
void
set_ext_type
(
uint8_t
*
ext_types
,
uint8_t
type
)
{
ext_types
[
type
/
8
]
=
(
uint8_t
)(
ext_types
[
type
/
8
]
|
(
1
<<
(
type
&
0x7
)));
}
void
nghttp2_option_set_user_recv_extension_type
(
nghttp2_option
*
option
,
uint8_t
type
)
{
if
(
type
<
10
)
{
...
...
@@ -70,8 +74,17 @@ void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
}
option
->
opt_set_mask
|=
NGHTTP2_OPT_USER_RECV_EXT_TYPES
;
option
->
user_recv_ext_types
[
type
/
8
]
=
(
uint8_t
)(
option
->
user_recv_ext_types
[
type
/
8
]
|
(
1
<<
(
type
&
0x7
)));
set_ext_type
(
option
->
user_recv_ext_types
,
type
);
}
void
nghttp2_option_set_builtin_recv_extension_type
(
nghttp2_option
*
option
,
uint8_t
type
)
{
if
(
type
<
10
)
{
return
;
}
option
->
opt_set_mask
|=
NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES
;
set_ext_type
(
option
->
builtin_recv_ext_types
,
type
);
}
void
nghttp2_option_set_no_auto_ping_ack
(
nghttp2_option
*
option
,
int
val
)
{
...
...
lib/nghttp2_option.h
View file @
795ee8c2
...
...
@@ -61,7 +61,8 @@ typedef enum {
NGHTTP2_OPT_NO_HTTP_MESSAGING
=
1
<<
3
,
NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS
=
1
<<
4
,
NGHTTP2_OPT_USER_RECV_EXT_TYPES
=
1
<<
5
,
NGHTTP2_OPT_NO_AUTO_PING_ACK
=
1
<<
6
NGHTTP2_OPT_NO_AUTO_PING_ACK
=
1
<<
6
,
NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES
=
1
<<
7
}
nghttp2_option_flag
;
/**
...
...
@@ -101,6 +102,10 @@ struct nghttp2_option {
* NGHTTP2_OPT_USER_RECV_EXT_TYPES
*/
uint8_t
user_recv_ext_types
[
32
];
/**
* NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES
*/
uint8_t
builtin_recv_ext_types
[
32
];
};
#endif
/* NGHTTP2_OPTION_H */
lib/nghttp2_outbound_item.c
View file @
795ee8c2
...
...
@@ -90,6 +90,8 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
assert
(
0
);
break
;
}
nghttp2_mem_free
(
mem
,
frame
->
ext
.
payload
);
}
}
}
...
...
lib/nghttp2_session.c
View file @
795ee8c2
...
...
@@ -142,6 +142,10 @@ static int session_detect_idle_stream(nghttp2_session *session,
return
0
;
}
static
int
check_ext_type_set
(
const
uint8_t
*
ext_types
,
uint8_t
type
)
{
return
(
ext_types
[
type
/
8
]
&
(
1
<<
(
type
&
0x7
)))
>
0
;
}
static
int
session_call_error_callback
(
nghttp2_session
*
session
,
const
char
*
fmt
,
...)
{
size_t
bufsize
;
...
...
@@ -316,7 +320,18 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
break
;
default:
/* extension frame */
nghttp2_frame_extension_free
(
&
iframe
->
frame
.
ext
);
if
(
check_ext_type_set
(
session
->
user_recv_ext_types
,
iframe
->
frame
.
hd
.
type
))
{
nghttp2_frame_extension_free
(
&
iframe
->
frame
.
ext
);
}
else
if
(
check_ext_type_set
(
session
->
builtin_recv_ext_types
,
iframe
->
frame
.
hd
.
type
))
{
switch
(
iframe
->
frame
.
hd
.
type
)
{
case
NGHTTP2_ALTSVC
:
nghttp2_frame_altsvc_free
(
&
iframe
->
frame
.
ext
,
mem
);
break
;
}
}
break
;
}
...
...
@@ -332,6 +347,8 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
nghttp2_buf_free
(
&
iframe
->
lbuf
,
mem
);
nghttp2_buf_wrap_init
(
&
iframe
->
lbuf
,
NULL
,
0
);
iframe
->
raw_lbuf
=
NULL
;
iframe
->
niv
=
0
;
iframe
->
payloadleft
=
0
;
iframe
->
padlen
=
0
;
...
...
@@ -474,6 +491,12 @@ static int session_new(nghttp2_session **session_ptr,
sizeof
((
*
session_ptr
)
->
user_recv_ext_types
));
}
if
(
option
->
opt_set_mask
&
NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES
)
{
memcpy
((
*
session_ptr
)
->
builtin_recv_ext_types
,
option
->
builtin_recv_ext_types
,
sizeof
((
*
session_ptr
)
->
builtin_recv_ext_types
));
}
if
((
option
->
opt_set_mask
&
NGHTTP2_OPT_NO_AUTO_PING_ACK
)
&&
option
->
no_auto_ping_ack
)
{
(
*
session_ptr
)
->
opt_flags
|=
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK
;
...
...
@@ -4637,6 +4660,44 @@ static int session_process_window_update_frame(nghttp2_session *session) {
return
nghttp2_session_on_window_update_received
(
session
,
frame
);
}
int
nghttp2_session_on_altsvc_received
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
)
{
nghttp2_ext_altsvc
*
altsvc
;
altsvc
=
frame
->
ext
.
payload
;
if
(
session
->
server
)
{
return
0
;
}
if
(
frame
->
hd
.
stream_id
==
0
)
{
if
(
altsvc
->
origin_len
==
0
)
{
return
0
;
}
}
else
if
(
altsvc
->
origin_len
>
0
)
{
return
0
;
}
return
session_call_on_frame_received
(
session
,
frame
);
}
static
int
session_process_altsvc_frame
(
nghttp2_session
*
session
)
{
nghttp2_inbound_frame
*
iframe
=
&
session
->
iframe
;
nghttp2_frame
*
frame
=
&
iframe
->
frame
;
frame
->
ext
.
payload
=
&
iframe
->
ext_frame_payload
.
altsvc
;
nghttp2_frame_unpack_altsvc_payload
(
&
frame
->
ext
,
nghttp2_get_uint16
(
iframe
->
sbuf
.
pos
),
iframe
->
lbuf
.
pos
,
nghttp2_buf_len
(
&
iframe
->
lbuf
));
/* nghttp2_frame_unpack_altsvc_payload steals buffer from
iframe->lbuf */
nghttp2_buf_wrap_init
(
&
iframe
->
lbuf
,
NULL
,
0
);
return
nghttp2_session_on_altsvc_received
(
session
,
frame
);
}
static
int
session_process_extension_frame
(
nghttp2_session
*
session
)
{
int
rv
;
nghttp2_inbound_frame
*
iframe
=
&
session
->
iframe
;
...
...
@@ -5480,25 +5541,59 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
break
;
default:
DEBUGF
(
fprintf
(
stderr
,
"recv:
unknow
n frame
\n
"
));
DEBUGF
(
fprintf
(
stderr
,
"recv:
extensio
n frame
\n
"
));
if
(
!
session
->
callbacks
.
unpack_extension_callback
||
(
session
->
user_recv_ext_types
[
iframe
->
frame
.
hd
.
type
/
8
]
&
(
1
<<
(
iframe
->
frame
.
hd
.
type
&
0x7
)))
==
0
)
{
/* Silently ignore unknown frame type. */
if
(
check_ext_type_set
(
session
->
user_recv_ext_types
,
iframe
->
frame
.
hd
.
type
))
{
if
(
!
session
->
callbacks
.
unpack_extension_callback
)
{
/* Silently ignore unknown frame type. */
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
break
;
}
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_
IG
N_PAYLOAD
;
iframe
->
state
=
NGHTTP2_IB_
READ_EXTENSIO
N_PAYLOAD
;
break
;
}
}
else
if
(
check_ext_type_set
(
session
->
builtin_recv_ext_types
,
iframe
->
frame
.
hd
.
type
))
{
switch
(
iframe
->
frame
.
hd
.
type
)
{
case
NGHTTP2_ALTSVC
:
DEBUGF
(
fprintf
(
stderr
,
"recv: ALTSVC
\n
"
));
busy
=
1
;
iframe
->
frame
.
hd
.
flags
=
NGHTTP2_FLAG_NONE
;
iframe
->
state
=
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
;
if
(
iframe
->
payloadleft
<
2
)
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_FRAME_SIZE_ERROR
;
break
;
}
break
;
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_READ_NBYTE
;
inbound_frame_set_mark
(
iframe
,
2
);
break
;
default:
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
break
;
}
}
else
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
break
;
}
}
if
(
!
on_begin_frame_called
)
{
...
...
@@ -5708,6 +5803,37 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
session_inbound_frame_reset
(
session
);
break
;
case
NGHTTP2_ALTSVC
:
{
size_t
origin_len
;
origin_len
=
nghttp2_get_uint16
(
iframe
->
sbuf
.
pos
);
DEBUGF
(
fprintf
(
stderr
,
"recv: origin_len=%zu
\n
"
,
origin_len
));
if
(
2
+
origin_len
>
iframe
->
payloadleft
)
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_FRAME_SIZE_ERROR
;
break
;
}
if
(
iframe
->
frame
.
hd
.
length
>
2
)
{
iframe
->
raw_lbuf
=
nghttp2_mem_malloc
(
mem
,
iframe
->
frame
.
hd
.
length
-
2
);
if
(
iframe
->
raw_lbuf
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
nghttp2_buf_wrap_init
(
&
iframe
->
lbuf
,
iframe
->
raw_lbuf
,
iframe
->
frame
.
hd
.
length
);
}
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_READ_ALTSVC_PAYLOAD
;
break
;
}
default:
/* This is unknown frame */
session_inbound_frame_reset
(
session
);
...
...
@@ -6233,6 +6359,36 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
session_inbound_frame_reset
(
session
);
break
;
case
NGHTTP2_IB_READ_ALTSVC_PAYLOAD
:
DEBUGF
(
fprintf
(
stderr
,
"recv: [IB_READ_ALTSVC_PAYLOAD]
\n
"
));
readlen
=
inbound_frame_payload_readlen
(
iframe
,
in
,
last
);
if
(
readlen
>
0
)
{
iframe
->
lbuf
.
last
=
nghttp2_cpymem
(
iframe
->
lbuf
.
last
,
in
,
readlen
);
iframe
->
payloadleft
-=
readlen
;
in
+=
readlen
;
}
DEBUGF
(
fprintf
(
stderr
,
"recv: readlen=%zu, payloadleft=%zu
\n
"
,
readlen
,
iframe
->
payloadleft
));
if
(
iframe
->
payloadleft
)
{
assert
(
nghttp2_buf_avail
(
&
iframe
->
lbuf
)
>
0
);
break
;
}
rv
=
session_process_altsvc_frame
(
session
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
session_inbound_frame_reset
(
session
);
break
;
}
...
...
lib/nghttp2_session.h
View file @
795ee8c2
...
...
@@ -107,6 +107,7 @@ typedef enum {
NGHTTP2_IB_READ_DATA
,
NGHTTP2_IB_IGN_DATA
,
NGHTTP2_IB_IGN_ALL
,
NGHTTP2_IB_READ_ALTSVC_PAYLOAD
,
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
}
nghttp2_inbound_state
;
...
...
@@ -313,6 +314,7 @@ struct nghttp2_session {
bit is set, it indicates that incoming frame with that type is
passed to user defined callbacks, otherwise they are ignored. */
uint8_t
user_recv_ext_types
[
32
];
uint8_t
builtin_recv_ext_types
[
32
];
};
/* Struct used when updating initial window size of each active
...
...
@@ -716,6 +718,19 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
int
nghttp2_session_on_window_update_received
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
);
/*
* Called when ALTSVC is recieved, assuming |frame| is properly
* initialized.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_CALLBACK_FAILURE
* The callback function failed.
*/
int
nghttp2_session_on_altsvc_received
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
);
/*
* Called when DATA is received, assuming |frame| is properly
* initialized.
...
...
lib/nghttp2_submit.c
View file @
795ee8c2
...
...
@@ -485,6 +485,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
rv
=
nghttp2_session_add_item
(
session
,
item
);
if
(
rv
!=
0
)
{
nghttp2_frame_altsvc_free
(
&
frame
->
ext
,
mem
);
nghttp2_mem_free
(
mem
,
frame
->
ext
.
payload
);
nghttp2_mem_free
(
mem
,
item
);
return
rv
;
...
...
src/nghttp.cc
View file @
795ee8c2
...
...
@@ -118,6 +118,7 @@ Config::Config()
nghttp2_option_new
(
&
http2_option
);
nghttp2_option_set_peer_max_concurrent_streams
(
http2_option
,
peer_max_concurrent_streams
);
nghttp2_option_set_builtin_recv_extension_type
(
http2_option
,
NGHTTP2_ALTSVC
);
}
Config
::~
Config
()
{
nghttp2_option_del
(
http2_option
);
}
...
...
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