Commit a46ccdb1 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Apply initiated SETTINGS changes on reception of ACK

parent 2afa9f75
......@@ -127,6 +127,13 @@ typedef struct {
*/
#define NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ((1 << 16) - 1)
/**
* @macro
*
* The maximum header table size.
*/
#define NGHTTP2_MAX_HEADER_TABLE_SIZE (1 << 16)
/**
* @macro
*
......@@ -262,6 +269,11 @@ typedef enum {
* Callback was paused by the application
*/
NGHTTP2_ERR_PAUSE = -526,
/**
* There are too many in-flight SETTING frame and no more
* transmission of SETTINGS is allowed.
*/
NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS = -527,
/**
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
* under unexpected condition and cannot process any further data
......@@ -379,9 +391,9 @@ typedef enum {
*/
NGHTTP2_FLAG_END_PUSH_PROMISE = 0x4,
/**
* The PONG flag.
* The ACK flag.
*/
NGHTTP2_FLAG_PONG = 0x1
NGHTTP2_FLAG_ACK = 0x1
} nghttp2_flag;
/**
......
......@@ -106,12 +106,11 @@ void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame)
{}
void nghttp2_frame_settings_init(nghttp2_settings *frame,
void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
nghttp2_settings_entry *iv, size_t niv)
{
memset(frame, 0, sizeof(nghttp2_settings));
nghttp2_frame_set_hd(&frame->hd, niv*8, NGHTTP2_SETTINGS, NGHTTP2_FLAG_NONE,
0);
nghttp2_frame_set_hd(&frame->hd, niv*8, NGHTTP2_SETTINGS, flags, 0);
frame->niv = niv;
frame->iv = iv;
}
......
......@@ -470,7 +470,7 @@ void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame);
* ownership of |iv|, so caller must not free it. The |flags| are
* bitwise-OR of one or more of nghttp2_settings_flag.
*/
void nghttp2_frame_settings_init(nghttp2_settings *frame,
void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
nghttp2_settings_entry *iv, size_t niv);
void nghttp2_frame_settings_free(nghttp2_settings *frame);
......
This diff is collapsed.
......@@ -188,6 +188,13 @@ struct nghttp2_session {
/* Settings value of the local endpoint. */
uint32_t local_settings[NGHTTP2_SETTINGS_MAX+1];
/* In-flight SETTINGS values. NULL does not necessarily mean there
is no in-flight SETTINGS. */
nghttp2_settings_entry *inflight_iv;
/* The number of entries in |inflight_iv|. -1 if there is no
in-flight SETTINGS. */
ssize_t inflight_niv;
/* Option flags. This is bitwise-OR of 0 or more of nghttp2_optmask. */
uint32_t opt_flags;
......@@ -295,6 +302,18 @@ int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
int32_t window_size_increment);
/*
* Adds SETTINGS frame.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
const nghttp2_settings_entry *iv, size_t niv);
/*
* Creates new stream in |session| with stream ID |stream_id|,
* priority |pri| and flags |flags|. NGHTTP2_FLAG_END_STREAM flag is
......@@ -386,19 +405,33 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
* Called when RST_STREAM is received, assuming |frame| is properly
* initialized.
*
* This function returns 0 and never fail.
* This function returns 0 if it succeeds, or one the following
* negative error codes:
*
* TBD
*/
int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
nghttp2_frame *frame);
/*
* Called when SETTINGS is received, assuming |frame| is properly
* initialized.
* initialized. If |noack| is non-zero, SETTINGS with ACK will not be
* submitted. If |frame| has NGHTTP2_FLAG_ACK flag set, no SETTINGS
* with ACK will not be submitted regardless of |noack|.
*
* This function returns 0 and never fail.
* This function returns 0 if it succeeds, or one the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
* NGHTTP2_ERR_PAUSE
* Callback function returns NGHTTP2_ERR_PAUSE
* NGHTTP2_ERR_CALLBACK_FAILURE
* The read_callback failed
*/
int nghttp2_session_on_settings_received(nghttp2_session *session,
nghttp2_frame *frame);
nghttp2_frame *frame,
int noack);
/*
* Called when PUSH_PROMISE is received, assuming |frame| is properly
......
......@@ -209,39 +209,7 @@ int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
const nghttp2_settings_entry *iv, size_t niv)
{
nghttp2_frame *frame;
nghttp2_settings_entry *iv_copy;
int r;
if(!nghttp2_iv_check(iv, niv,
session->local_settings
[NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS])) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
return NGHTTP2_ERR_NOMEM;
}
iv_copy = nghttp2_frame_iv_copy(iv, niv);
if(iv_copy == NULL) {
free(frame);
return NGHTTP2_ERR_NOMEM;
}
nghttp2_frame_settings_init(&frame->settings, iv_copy, niv);
r = nghttp2_session_update_local_settings(session, iv_copy, niv);
if(r != 0) {
nghttp2_frame_settings_free(&frame->settings);
free(frame);
return r;
}
r = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
if(r != 0) {
/* The only expected error is fatal one */
assert(r < NGHTTP2_ERR_FATAL);
nghttp2_frame_settings_free(&frame->settings);
free(frame);
}
return r;
return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
}
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
......
......@@ -80,12 +80,16 @@ namespace {
const char* strsettingsid(int32_t id)
{
switch(id) {
case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
return "SETTINGS_HEADER_TABLE_SIZE";
case NGHTTP2_SETTINGS_ENABLE_PUSH:
return "SETTINGS_ENABLE_PUSH";
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
return "MAX_CONCURRENT_STREAMS";
return "SETTINGS_MAX_CONCURRENT_STREAMS";
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
return "INITIAL_WINDOW_SIZE";
return "SETTINGS_INITIAL_WINDOW_SIZE";
case NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS:
return "FLOW_CONTROL_OPTIONS";
return "SETTINGS_FLOW_CONTROL_OPTIONS";
default:
return "UNKNOWN";
}
......@@ -208,14 +212,19 @@ void print_flags(const nghttp2_frame_hd& hd)
s += "PRIORITY";
}
break;
case NGHTTP2_SETTINGS:
if(hd.flags & NGHTTP2_FLAG_ACK) {
s += "ACK";
}
break;
case NGHTTP2_PUSH_PROMISE:
if(hd.flags & NGHTTP2_FLAG_END_PUSH_PROMISE) {
s += "END_PUSH_PROMISE";
}
break;
case NGHTTP2_PING:
if(hd.flags & NGHTTP2_FLAG_PONG) {
s += "PONG";
if(hd.flags & NGHTTP2_FLAG_ACK) {
s += "ACK";
}
break;
}
......
......@@ -223,7 +223,8 @@ void test_nghttp2_frame_pack_settings()
iv[2].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
iv[2].value = 1;
nghttp2_frame_settings_init(&frame, nghttp2_frame_iv_copy(iv, 3), 3);
nghttp2_frame_settings_init(&frame, NGHTTP2_FLAG_NONE,
nghttp2_frame_iv_copy(iv, 3), 3);
framelen = nghttp2_frame_pack_settings(&buf, &buflen, &frame);
CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH+3*8 == framelen);
......@@ -290,14 +291,14 @@ void test_nghttp2_frame_pack_ping(void)
size_t buflen = 0;
ssize_t framelen;
const uint8_t opaque_data[] = "01234567";
nghttp2_frame_ping_init(&frame, NGHTTP2_FLAG_PONG, opaque_data);
nghttp2_frame_ping_init(&frame, NGHTTP2_FLAG_ACK, opaque_data);
framelen = nghttp2_frame_pack_ping(&buf, &buflen, &frame);
CU_ASSERT(0 == nghttp2_frame_unpack_ping
(&oframe,
&buf[0], NGHTTP2_FRAME_HEAD_LENGTH,
&buf[NGHTTP2_FRAME_HEAD_LENGTH],
framelen - NGHTTP2_FRAME_HEAD_LENGTH));
check_frame_header(8, NGHTTP2_PING, NGHTTP2_FLAG_PONG, 0, &oframe.hd);
check_frame_header(8, NGHTTP2_PING, NGHTTP2_FLAG_ACK, 0, &oframe.hd);
CU_ASSERT(memcmp(opaque_data, oframe.opaque_data, sizeof(opaque_data) - 1)
== 0);
free(buf);
......
This diff is collapsed.
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