Add API for HTTP Upgrade
This commit is contained in:
parent
5594f0ef0b
commit
737ac01d91
|
@ -1323,6 +1323,72 @@ size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session);
|
|||
int nghttp2_session_fail_session(nghttp2_session *session,
|
||||
nghttp2_error_code error_code);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Performs post-process of HTTP Upgrade request. This function can be
|
||||
* called from both client and server, but the behavior is very
|
||||
* different in each other.
|
||||
*
|
||||
* If called from client side, the |settings_payload| must be the
|
||||
* value sent in HTTP2-Settings header field and must be decoded by
|
||||
* base64url decoder. The |settings_payloadlen| is the length of
|
||||
* |settings_payload|. The |settings_payload| is unpacked and its
|
||||
* setting values will be submitted using
|
||||
* nghttp2_submit_settings(). This means that the client application
|
||||
* code does not need to submit SETTINGS by itself. The stream with
|
||||
* stream ID=1 is opened and the |stream_user_data| is used for its
|
||||
* stream_user_data. The opened stream becomes half-closed (local)
|
||||
* state.
|
||||
*
|
||||
* If called from server side, the |settings_payload| must be the
|
||||
* value received in HTTP2-Settings header field and must be decoded
|
||||
* by base64url decoder. The |settings_payloadlen| is the length of
|
||||
* |settings_payload|. It is treated as if the SETTINGS frame with
|
||||
* that payload is received. Thus, callback functions for the
|
||||
* reception of SETTINGS frame will be invoked. The stream with stream
|
||||
* ID=1 is opened. The |stream_user_data| is ignored. The opened
|
||||
* stream becomes half-closed (remote).
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||
* Out of memory.
|
||||
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |settings_payload| is badly formed.
|
||||
* :enum:`NGHTTP2_ERR_PROTO`
|
||||
* The stream ID 1 is already used or closed; or is not available;
|
||||
* or the |settings_payload| does not include both
|
||||
* NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS and
|
||||
* NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE.
|
||||
*/
|
||||
int nghttp2_session_upgrade(nghttp2_session *session,
|
||||
const uint8_t *settings_payload,
|
||||
size_t settings_payloadlen,
|
||||
void *stream_user_data);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Serializes the SETTINGS values |iv| in the |buf|. The number of
|
||||
* entry pointed by |iv| array is given by the |niv|. This function
|
||||
* may reorder the pointers in |iv|. The |buf| must have enough region
|
||||
* to hold serialized data. The required space for the |niv| entries
|
||||
* are 8*|niv| bytes. This function is used mainly for creating
|
||||
* SETTINGS payload to be sent with HTTP2-Settings header field in
|
||||
* HTTP Upgrade request. The data written in |buf| is not still
|
||||
* base64url encoded and the application is responsible to do that.
|
||||
*
|
||||
* This function returns the number of bytes written in |buf|, or one
|
||||
* of the following negative error codes:
|
||||
*
|
||||
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||
* The |iv| contains duplicate settings ID or invalid value.
|
||||
*/
|
||||
ssize_t nghttp2_pack_settings_payload(uint8_t *buf,
|
||||
nghttp2_settings_entry *iv, size_t niv);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
|
|
|
@ -467,7 +467,6 @@ ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
|
|||
nghttp2_settings *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
|
||||
size_t i;
|
||||
int r;
|
||||
r = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
if(r != 0) {
|
||||
|
@ -475,33 +474,55 @@ ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
|
|||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
for(i = 0; i < frame->niv; ++i) {
|
||||
int off = i*8;
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[8+off], frame->iv[i].settings_id);
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[12+off], frame->iv[i].value);
|
||||
}
|
||||
nghttp2_frame_pack_settings_payload(*buf_ptr + 8, frame->iv, frame->niv);
|
||||
return framelen;
|
||||
}
|
||||
|
||||
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < niv; ++i, buf += 8) {
|
||||
nghttp2_put_uint32be(buf, iv[i].settings_id);
|
||||
nghttp2_put_uint32be(buf + 4, iv[i].value);
|
||||
}
|
||||
return 8 * niv;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_settings(nghttp2_settings *frame,
|
||||
const uint8_t *head, size_t headlen,
|
||||
const uint8_t *payload, size_t payloadlen)
|
||||
{
|
||||
size_t i;
|
||||
int rv;
|
||||
if(payloadlen % 8) {
|
||||
return NGHTTP2_ERR_INVALID_FRAME;
|
||||
}
|
||||
nghttp2_frame_unpack_frame_hd(&frame->hd, head);
|
||||
frame->niv = payloadlen / 8;
|
||||
frame->iv = malloc(frame->niv*sizeof(nghttp2_settings_entry));
|
||||
if(frame->iv == NULL) {
|
||||
rv = nghttp2_frame_unpack_settings_payload(&frame->iv, &frame->niv,
|
||||
payload, payloadlen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings_entry **iv_ptr,
|
||||
size_t *niv_ptr,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen)
|
||||
{
|
||||
size_t i;
|
||||
*niv_ptr = payloadlen / 8;
|
||||
*iv_ptr = malloc((*niv_ptr)*sizeof(nghttp2_settings_entry));
|
||||
if(*iv_ptr == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
for(i = 0; i < frame->niv; ++i) {
|
||||
for(i = 0; i < *niv_ptr; ++i) {
|
||||
size_t off = i*8;
|
||||
frame->iv[i].settings_id = nghttp2_get_uint32(&payload[off]) &
|
||||
(*iv_ptr)[i].settings_id = nghttp2_get_uint32(&payload[off]) &
|
||||
NGHTTP2_SETTINGS_ID_MASK;
|
||||
frame->iv[i].value = nghttp2_get_uint32(&payload[4+off]);
|
||||
(*iv_ptr)[i].value = nghttp2_get_uint32(&payload[4+off]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -809,3 +830,20 @@ ssize_t nghttp2_nv_array_from_cstr(nghttp2_nv **nva_ptr, const char **nv)
|
|||
nghttp2_nv_array_sort(*nva_ptr, nvlen);
|
||||
return nvlen;
|
||||
}
|
||||
|
||||
int nghttp2_settings_check_duplicate(const nghttp2_settings_entry *iv,
|
||||
size_t niv)
|
||||
{
|
||||
int check[NGHTTP2_SETTINGS_MAX+1];
|
||||
size_t i;
|
||||
memset(check, 0, sizeof(check));
|
||||
for(i = 0; i < niv; ++i) {
|
||||
if(iv[i].settings_id > NGHTTP2_SETTINGS_MAX || iv[i].settings_id == 0 ||
|
||||
check[iv[i].settings_id] == 1) {
|
||||
return 0;
|
||||
} else {
|
||||
check[iv[i].settings_id] = 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -223,6 +223,16 @@ int nghttp2_frame_unpack_rst_stream(nghttp2_rst_stream *frame,
|
|||
ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_settings *frame);
|
||||
|
||||
/*
|
||||
* Packs the |iv|, which includes |niv| entries, in the |buf|,
|
||||
* assuming the |buf| has at least 8 * |niv| bytes.
|
||||
*
|
||||
* Returns the number of bytes written into the |buf|.
|
||||
*/
|
||||
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Unpacks SETTINGS wire format into |frame|.
|
||||
*
|
||||
|
@ -239,6 +249,23 @@ int nghttp2_frame_unpack_settings(nghttp2_settings *frame,
|
|||
const uint8_t *payload, size_t payloadlen);
|
||||
|
||||
|
||||
/*
|
||||
* Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
|
||||
* assigned to the |*niv_ptr|. This function allocates enough memory
|
||||
* to store the result in |*iv_ptr|. The caller is responsible to free
|
||||
* |*iv_ptr| after its use.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings_entry **iv_ptr,
|
||||
size_t *niv_ptr,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs PUSH_PROMISE frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
|
||||
|
@ -600,4 +627,13 @@ void nghttp2_nv_array_del(nghttp2_nv *nva);
|
|||
int nghttp2_nv_array_check_null(nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
|
||||
/*
|
||||
* Checks that the |iv|, which includes |niv| entries, does not have
|
||||
* duplicate IDs.
|
||||
*
|
||||
* This function returns nonzero if it succeeds, or 0.
|
||||
*/
|
||||
int nghttp2_settings_check_duplicate(const nghttp2_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
|
|
|
@ -357,7 +357,7 @@ int nghttp2_session_add_frame(nghttp2_session *session,
|
|||
break;
|
||||
}
|
||||
case NGHTTP2_SETTINGS:
|
||||
/* Should NGHTTP2_SETTINGS have higher priority? */
|
||||
/* Should NGHTTP2_SETTINGS have higher priority? Yes */
|
||||
item->pri = -1;
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE: {
|
||||
|
@ -2986,3 +2986,69 @@ int nghttp2_session_set_option(nghttp2_session *session,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_session_upgrade(nghttp2_session *session,
|
||||
const uint8_t *settings_payload,
|
||||
size_t settings_payloadlen,
|
||||
void *stream_user_data)
|
||||
{
|
||||
nghttp2_stream *stream;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_settings_entry *iv;
|
||||
size_t niv;
|
||||
int rv;
|
||||
int max_conn_val_seen = 0;
|
||||
int ini_win_size_seen = 0;
|
||||
size_t i;
|
||||
|
||||
if((!session->server && session->next_stream_id != 1) ||
|
||||
(session->server && session->last_recv_stream_id >= 1)) {
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
if(settings_payloadlen % 8) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
rv = nghttp2_frame_unpack_settings_payload(&iv, &niv, settings_payload,
|
||||
settings_payloadlen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
for(i = 0; i < niv; ++i) {
|
||||
if(iv[i].settings_id == NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) {
|
||||
max_conn_val_seen = 1;
|
||||
} else if(iv[i].settings_id == NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
|
||||
ini_win_size_seen = 1;
|
||||
}
|
||||
}
|
||||
if(!max_conn_val_seen || !ini_win_size_seen) {
|
||||
free(iv);
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
if(session->server) {
|
||||
memset(&frame.hd, 0, sizeof(frame.hd));
|
||||
frame.settings.iv = iv;
|
||||
frame.settings.niv = niv;
|
||||
rv = nghttp2_session_on_settings_received(session, &frame);
|
||||
} else {
|
||||
rv = nghttp2_submit_settings(session, iv, niv);
|
||||
}
|
||||
free(iv);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
stream = nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
|
||||
0, NGHTTP2_STREAM_OPENING,
|
||||
session->server ?
|
||||
NULL : stream_user_data);
|
||||
if(stream == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
if(session->server) {
|
||||
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
|
||||
session->last_recv_stream_id = 1;
|
||||
} else {
|
||||
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
|
||||
session->next_stream_id += 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -153,17 +153,9 @@ int nghttp2_submit_settings(nghttp2_session *session,
|
|||
{
|
||||
nghttp2_frame *frame;
|
||||
nghttp2_settings_entry *iv_copy;
|
||||
int check[NGHTTP2_SETTINGS_MAX+1];
|
||||
size_t i;
|
||||
int r;
|
||||
memset(check, 0, sizeof(check));
|
||||
for(i = 0; i < niv; ++i) {
|
||||
if(iv[i].settings_id > NGHTTP2_SETTINGS_MAX || iv[i].settings_id == 0 ||
|
||||
check[iv[i].settings_id] == 1) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
} else {
|
||||
check[iv[i].settings_id] = 1;
|
||||
}
|
||||
if(!nghttp2_settings_check_duplicate(iv, niv)) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
frame = malloc(sizeof(nghttp2_frame));
|
||||
if(frame == NULL) {
|
||||
|
@ -297,3 +289,13 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
|||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_pack_settings_payload(uint8_t *buf,
|
||||
nghttp2_settings_entry *iv, size_t niv)
|
||||
{
|
||||
if(!nghttp2_settings_check_duplicate(iv, niv)) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
nghttp2_frame_iv_sort(iv, niv);
|
||||
return nghttp2_frame_pack_settings_payload(buf, iv, niv);
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_send_push_promise) ||
|
||||
!CU_add_test(pSuite, "session_is_my_stream_id",
|
||||
test_nghttp2_session_is_my_stream_id) ||
|
||||
!CU_add_test(pSuite, "session_upgrade", test_nghttp2_session_upgrade) ||
|
||||
!CU_add_test(pSuite, "submit_response", test_nghttp2_submit_response) ||
|
||||
!CU_add_test(pSuite, "submit_response_without_data",
|
||||
test_nghttp2_submit_response_without_data) ||
|
||||
|
@ -183,6 +184,8 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_set_option) ||
|
||||
!CU_add_test(pSuite, "session_data_backoff_by_high_pri_frame",
|
||||
test_nghttp2_session_data_backoff_by_high_pri_frame) ||
|
||||
!CU_add_test(pSuite, "pack_settings_payload",
|
||||
test_nghttp2_pack_settings_payload) ||
|
||||
!CU_add_test(pSuite, "frame_nv_sort", test_nghttp2_frame_nv_sort) ||
|
||||
!CU_add_test(pSuite, "frame_nv_downcase",
|
||||
test_nghttp2_frame_nv_downcase) ||
|
||||
|
@ -207,6 +210,8 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_frame_pack_window_update) ||
|
||||
!CU_add_test(pSuite, "nv_array_from_cstr",
|
||||
test_nghttp2_nv_array_from_cstr) ||
|
||||
!CU_add_test(pSuite, "settings_check_duplicate",
|
||||
test_nghttp2_settings_check_duplicate) ||
|
||||
!CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_indname_inc",
|
||||
test_nghttp2_hd_inflate_indname_inc) ||
|
||||
|
|
|
@ -417,3 +417,27 @@ void test_nghttp2_nv_array_from_cstr(void)
|
|||
|
||||
free(bigval);
|
||||
}
|
||||
|
||||
void test_nghttp2_settings_check_duplicate(void)
|
||||
{
|
||||
nghttp2_settings_entry set[3];
|
||||
|
||||
set[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
set[0].value = 1;
|
||||
set[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
set[1].value = 1023;
|
||||
|
||||
CU_ASSERT(nghttp2_settings_check_duplicate(set, 2));
|
||||
|
||||
set[1] = set[0];
|
||||
CU_ASSERT(0 == nghttp2_settings_check_duplicate(set, 2));
|
||||
|
||||
/* Out-of-bound data is error */
|
||||
set[0].settings_id = NGHTTP2_SETTINGS_MAX + 1;
|
||||
CU_ASSERT(0 == nghttp2_settings_check_duplicate(set, 1));
|
||||
|
||||
/* settings_id == 0 is error */
|
||||
set[0].settings_id = 0;
|
||||
CU_ASSERT(0 == nghttp2_settings_check_duplicate(set, 1));
|
||||
}
|
||||
|
||||
|
|
|
@ -38,5 +38,6 @@ void test_nghttp2_frame_pack_ping(void);
|
|||
void test_nghttp2_frame_pack_goaway(void);
|
||||
void test_nghttp2_frame_pack_window_update(void);
|
||||
void test_nghttp2_nv_array_from_cstr(void);
|
||||
void test_nghttp2_settings_check_duplicate(void);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_TEST_H */
|
||||
|
|
|
@ -1451,6 +1451,91 @@ void test_nghttp2_session_is_my_stream_id(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_upgrade(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
uint8_t settings_payload[128];
|
||||
size_t settings_payloadlen;
|
||||
nghttp2_settings_entry iv[16];
|
||||
nghttp2_stream *stream;
|
||||
nghttp2_outbound_item *item;
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[0].value = 1;
|
||||
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[1].value = 4095;
|
||||
settings_payloadlen = nghttp2_pack_settings_payload(settings_payload, iv, 2);
|
||||
|
||||
/* Check client side */
|
||||
nghttp2_session_client_new(&session, &callbacks, NULL);
|
||||
CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
|
||||
settings_payloadlen, &callbacks));
|
||||
stream = nghttp2_session_get_stream(session, 1);
|
||||
CU_ASSERT(stream != NULL);
|
||||
CU_ASSERT(&callbacks == stream->stream_user_data);
|
||||
CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
|
||||
item = nghttp2_session_get_next_ob_item(session);
|
||||
CU_ASSERT(NGHTTP2_SETTINGS == OB_CTRL_TYPE(item));
|
||||
CU_ASSERT(2 == OB_CTRL(item)->settings.niv);
|
||||
CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
|
||||
OB_CTRL(item)->settings.iv[0].settings_id);
|
||||
CU_ASSERT(1 == OB_CTRL(item)->settings.iv[0].value);
|
||||
CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
|
||||
OB_CTRL(item)->settings.iv[1].settings_id);
|
||||
CU_ASSERT(4095 == OB_CTRL(item)->settings.iv[1].value);
|
||||
|
||||
/* Call nghttp2_session_upgrade() again is error */
|
||||
CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_session_upgrade(session,
|
||||
settings_payload,
|
||||
settings_payloadlen,
|
||||
&callbacks));
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Check server side */
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
CU_ASSERT(0 == nghttp2_session_upgrade(session, settings_payload,
|
||||
settings_payloadlen, &callbacks));
|
||||
stream = nghttp2_session_get_stream(session, 1);
|
||||
CU_ASSERT(stream != NULL);
|
||||
CU_ASSERT(NULL == stream->stream_user_data);
|
||||
CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags);
|
||||
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
|
||||
CU_ASSERT(1 ==
|
||||
session->remote_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]);
|
||||
CU_ASSERT(4095 ==
|
||||
session->remote_settings[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
|
||||
/* Call nghttp2_session_upgrade() again is error */
|
||||
CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_session_upgrade(session,
|
||||
settings_payload,
|
||||
settings_payloadlen,
|
||||
&callbacks));
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Check required settings */
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[0].value = 1;
|
||||
settings_payloadlen = nghttp2_pack_settings_payload(settings_payload, iv, 1);
|
||||
|
||||
nghttp2_session_client_new(&session, &callbacks, NULL);
|
||||
CU_ASSERT(NGHTTP2_ERR_PROTO ==
|
||||
nghttp2_session_upgrade(session, settings_payload,
|
||||
settings_payloadlen, NULL));
|
||||
nghttp2_session_del(session);
|
||||
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[0].value = 4095;
|
||||
settings_payloadlen = nghttp2_pack_settings_payload(settings_payload, iv, 1);
|
||||
|
||||
nghttp2_session_client_new(&session, &callbacks, NULL);
|
||||
CU_ASSERT(NGHTTP2_ERR_PROTO ==
|
||||
nghttp2_session_upgrade(session, settings_payload,
|
||||
settings_payloadlen, NULL));
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_submit_response(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
|
@ -2857,3 +2942,29 @@ void test_nghttp2_session_data_backoff_by_high_pri_frame(void)
|
|||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_pack_settings_payload(void)
|
||||
{
|
||||
nghttp2_settings_entry iv[2];
|
||||
uint8_t buf[64];
|
||||
size_t len;
|
||||
nghttp2_settings_entry *resiv;
|
||||
size_t resniv;
|
||||
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
|
||||
iv[0].value = 1;
|
||||
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[1].value = 4095;
|
||||
|
||||
len = nghttp2_pack_settings_payload(buf, iv, 2);
|
||||
CU_ASSERT(16 == len);
|
||||
CU_ASSERT(0 == nghttp2_frame_unpack_settings_payload(&resiv, &resniv,
|
||||
buf, len));
|
||||
CU_ASSERT(2 == resniv);
|
||||
CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE == resiv[0].settings_id);
|
||||
CU_ASSERT(4095 == resiv[0].value);
|
||||
CU_ASSERT(NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS == resiv[1].settings_id);
|
||||
CU_ASSERT(1 == resiv[1].value);
|
||||
|
||||
free(resiv);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ void test_nghttp2_session_send_priority(void);
|
|||
void test_nghttp2_session_send_rst_stream(void);
|
||||
void test_nghttp2_session_send_push_promise(void);
|
||||
void test_nghttp2_session_is_my_stream_id(void);
|
||||
void test_nghttp2_session_upgrade(void);
|
||||
void test_nghttp2_submit_response(void);
|
||||
void test_nghttp2_submit_response_without_data(void);
|
||||
void test_nghttp2_submit_request_with_data(void);
|
||||
|
@ -82,5 +83,6 @@ void test_nghttp2_session_on_ctrl_not_send(void);
|
|||
void test_nghttp2_session_get_outbound_queue_size(void);
|
||||
void test_nghttp2_session_set_option(void);
|
||||
void test_nghttp2_session_data_backoff_by_high_pri_frame(void);
|
||||
void test_nghttp2_pack_settings_payload(void);
|
||||
|
||||
#endif /* NGHTTP2_SESSION_TEST_H */
|
||||
|
|
Loading…
Reference in New Issue