Commit 061a5578 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Add nghttp2_option_set_user_recv_extension_type to opt-in incoming extension type

parent d9893d01
...@@ -2186,6 +2186,21 @@ NGHTTP2_EXTERN void ...@@ -2186,6 +2186,21 @@ NGHTTP2_EXTERN void
nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option, nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
uint32_t val); uint32_t val);
/**
* @function
*
* Set extension frame type the application is willing to handle with
* user defined callbacks (see
* :type:`nghttp2_on_extension_chunk_recv_callback` and
* :type:`nghttp2_unpack_extension_callback`). The |type| is
* extension frame type, and must be strictly greater than 0x9.
* Otherwise, this function does nothing. The application does not
* have to call this function if it just sends extension frames.
*/
NGHTTP2_EXTERN void
nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
uint8_t type);
/** /**
* @function * @function
* *
......
...@@ -62,3 +62,13 @@ void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option, ...@@ -62,3 +62,13 @@ void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
option->opt_set_mask |= NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS; option->opt_set_mask |= NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS;
option->max_reserved_remote_streams = val; option->max_reserved_remote_streams = val;
} }
void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
uint8_t type) {
if (type < 10) {
return;
}
option->opt_set_mask |= NGHTTP2_OPT_USER_RECV_EXT_TYPES;
option->user_recv_ext_types[type / 8] |= 1 << (7 - (type & 0x7));
}
...@@ -59,7 +59,8 @@ typedef enum { ...@@ -59,7 +59,8 @@ typedef enum {
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1, NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1,
NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2, NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2,
NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3, NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3,
NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4 NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4,
NGHTTP2_OPT_USER_RECV_EXT_TYPES = 1 << 5
} nghttp2_option_flag; } nghttp2_option_flag;
/** /**
...@@ -91,6 +92,10 @@ struct nghttp2_option { ...@@ -91,6 +92,10 @@ struct nghttp2_option {
* NGHTTP2_OPT_NO_HTTP_MESSAGING * NGHTTP2_OPT_NO_HTTP_MESSAGING
*/ */
int no_http_messaging; int no_http_messaging;
/**
* NGHTTP2_OPT_USER_RECV_EXT_TYPES
*/
uint8_t user_recv_ext_types[32];
}; };
#endif /* NGHTTP2_OPTION_H */ #endif /* NGHTTP2_OPTION_H */
...@@ -402,6 +402,11 @@ static int session_new(nghttp2_session **session_ptr, ...@@ -402,6 +402,11 @@ static int session_new(nghttp2_session **session_ptr,
(*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING; (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
} }
if (option->opt_set_mask & NGHTTP2_OPT_USER_RECV_EXT_TYPES) {
memcpy((*session_ptr)->user_recv_ext_types, option->user_recv_ext_types,
sizeof((*session_ptr)->user_recv_ext_types));
}
} }
(*session_ptr)->callbacks = *callbacks; (*session_ptr)->callbacks = *callbacks;
...@@ -5291,7 +5296,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in, ...@@ -5291,7 +5296,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
default: default:
DEBUGF(fprintf(stderr, "recv: unknown frame\n")); DEBUGF(fprintf(stderr, "recv: unknown frame\n"));
if (!session->callbacks.unpack_extension_callback) { if (!session->callbacks.unpack_extension_callback ||
(session->user_recv_ext_types[iframe->frame.hd.type / 8] &
(1 << (7 - (iframe->frame.hd.type & 0x7)))) == 0) {
/* Silently ignore unknown frame type. */ /* Silently ignore unknown frame type. */
busy = 1; busy = 1;
......
...@@ -296,6 +296,12 @@ struct nghttp2_session { ...@@ -296,6 +296,12 @@ struct nghttp2_session {
this session. The nonzero does not necessarily mean this session. The nonzero does not necessarily mean
WINDOW_UPDATE is not queued. */ WINDOW_UPDATE is not queued. */
uint8_t window_update_queued; uint8_t window_update_queued;
/* Bitfield of extension frame types that application is willing to
receive. First most significant 10 bits are standard frame types
and not used. If 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];
}; };
/* Struct used when updating initial window size of each active /* Struct used when updating initial window size of each active
......
...@@ -1769,6 +1769,7 @@ void test_nghttp2_session_recv_extension(void) { ...@@ -1769,6 +1769,7 @@ void test_nghttp2_session_recv_extension(void) {
nghttp2_mem *mem; nghttp2_mem *mem;
const char data[] = "Hello World!"; const char data[] = "Hello World!";
ssize_t rv; ssize_t rv;
nghttp2_option *option;
mem = nghttp2_mem_default(); mem = nghttp2_mem_default();
...@@ -1778,6 +1779,9 @@ void test_nghttp2_session_recv_extension(void) { ...@@ -1778,6 +1779,9 @@ void test_nghttp2_session_recv_extension(void) {
callbacks.unpack_extension_callback = unpack_extension_callback; callbacks.unpack_extension_callback = unpack_extension_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
nghttp2_option_new(&option);
nghttp2_option_set_user_recv_extension_type(option, 111);
nghttp2_buf_init2(&ud.scratchbuf, 4096, mem); nghttp2_buf_init2(&ud.scratchbuf, 4096, mem);
nghttp2_buf_init2(&buf, 4096, mem); nghttp2_buf_init2(&buf, 4096, mem);
...@@ -1786,7 +1790,7 @@ void test_nghttp2_session_recv_extension(void) { ...@@ -1786,7 +1790,7 @@ void test_nghttp2_session_recv_extension(void) {
buf.last += NGHTTP2_FRAME_HDLEN; buf.last += NGHTTP2_FRAME_HDLEN;
buf.last = nghttp2_cpymem(buf.last, data, sizeof(data)); buf.last = nghttp2_cpymem(buf.last, data, sizeof(data));
nghttp2_session_client_new(&session, &callbacks, &ud); nghttp2_session_client_new2(&session, &callbacks, &ud, option);
nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0); nghttp2_frame_hd_init(&ud.recv_frame_hd, 0, 0, 0, 0);
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
...@@ -1805,7 +1809,7 @@ void test_nghttp2_session_recv_extension(void) { ...@@ -1805,7 +1809,7 @@ void test_nghttp2_session_recv_extension(void) {
callbacks.on_extension_chunk_recv_callback = callbacks.on_extension_chunk_recv_callback =
cancel_on_extension_chunk_recv_callback; cancel_on_extension_chunk_recv_callback;
nghttp2_session_server_new(&session, &callbacks, &ud); nghttp2_session_server_new2(&session, &callbacks, &ud, option);
ud.frame_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
...@@ -1821,7 +1825,7 @@ void test_nghttp2_session_recv_extension(void) { ...@@ -1821,7 +1825,7 @@ void test_nghttp2_session_recv_extension(void) {
callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback; callbacks.on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
callbacks.unpack_extension_callback = cancel_unpack_extension_callback; callbacks.unpack_extension_callback = cancel_unpack_extension_callback;
nghttp2_session_server_new(&session, &callbacks, &ud); nghttp2_session_server_new2(&session, &callbacks, &ud, option);
ud.frame_recv_cb_called = 0; ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf)); rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
...@@ -1833,6 +1837,8 @@ void test_nghttp2_session_recv_extension(void) { ...@@ -1833,6 +1837,8 @@ void test_nghttp2_session_recv_extension(void) {
nghttp2_buf_free(&buf, mem); nghttp2_buf_free(&buf, mem);
nghttp2_buf_free(&ud.scratchbuf, mem); nghttp2_buf_free(&ud.scratchbuf, mem);
nghttp2_option_del(option);
} }
void test_nghttp2_session_continue(void) { void test_nghttp2_session_continue(void) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment