Remove NGHTTP2_FLAG_END_FLOW_CONTROL

This commit is contained in:
Tatsuhiro Tsujikawa 2013-08-18 22:04:09 +09:00
parent f222403970
commit 0c9703fa2c
10 changed files with 41 additions and 174 deletions

View File

@ -337,11 +337,7 @@ typedef enum {
/** /**
* The PONG flag. * The PONG flag.
*/ */
NGHTTP2_FLAG_PONG = 0x1, NGHTTP2_FLAG_PONG = 0x1
/**
* The END_FLOW_CONTROL flag.
*/
NGHTTP2_FLAG_END_FLOW_CONTROL = 0x1
} nghttp2_flag; } nghttp2_flag;
/** /**
@ -1738,6 +1734,8 @@ int nghttp2_submit_goaway(nghttp2_session *session,
* *
* Submits WINDOW_UPDATE frame. * Submits WINDOW_UPDATE frame.
* *
* The |flags| is currently ignored.
*
* If the |window_size_increment| is positive, the WINDOW_UPDATE with * If the |window_size_increment| is positive, the WINDOW_UPDATE with
* that value as window_size_increment is queued. If the * that value as window_size_increment is queued. If the
* |window_size_increment| is larger than the received bytes from the * |window_size_increment| is larger than the received bytes from the
@ -1756,9 +1754,7 @@ int nghttp2_submit_goaway(nghttp2_session *session,
* negative error codes: * negative error codes:
* *
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |delta_window_size| is 0 and * The |delta_window_size| is 0.
* :enum:`NGHTTP2_FLAG_END_FLOW_CONTROL` bit is not set in
* |flags|.
* :enum:`NGHTTP2_ERR_FLOW_CONTROL` * :enum:`NGHTTP2_ERR_FLOW_CONTROL`
* The local window size overflow or gets negative. * The local window size overflow or gets negative.
* :enum:`NGHTTP2_ERR_STREAM_CLOSED` * :enum:`NGHTTP2_ERR_STREAM_CLOSED`

View File

@ -2268,24 +2268,13 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
if(frame->hd.stream_id == 0) { if(frame->hd.stream_id == 0) {
/* Handle connection-level flow control */ /* Handle connection-level flow control */
if(session->remote_flow_control == 0) { if(session->remote_flow_control == 0) {
/* The sepc says receiving WINDOW_UPDATE from peer when flow /* Disabling flow control by sending SETTINGS and receiving
control is disabled is error, but disabling flow control and WINDOW_UPDATE are asynchronous, so it is hard to determine
receiving WINDOW_UPDATE are asynchronous, so it is hard to that the peer is misbehaving or not without measuring
determine that the peer is misbehaving or not without RTT. For now, we just ignore such frames. */
measuring RTT. For now, we just ignore such frames. */
nghttp2_session_call_on_frame_received(session, frame); nghttp2_session_call_on_frame_received(session, frame);
return 0; return 0;
} }
if(frame->hd.flags & NGHTTP2_FLAG_END_FLOW_CONTROL) {
if(session->remote_flow_control) {
/* Disable connection-level flow control and push back
deferred DATA frame if any */
session->remote_flow_control = 0;
nghttp2_session_call_on_frame_received(session, frame);
return nghttp2_session_push_back_deferred_data(session);
}
return 0;
}
if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
session->remote_window_size) { session->remote_window_size) {
return nghttp2_session_handle_invalid_connection return nghttp2_session_handle_invalid_connection
@ -2309,24 +2298,6 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
nghttp2_session_call_on_frame_received(session, frame); nghttp2_session_call_on_frame_received(session, frame);
return 0; return 0;
} }
if(frame->hd.flags & NGHTTP2_FLAG_END_FLOW_CONTROL) {
stream->remote_flow_control = 0;
if(stream->remote_flow_control &&
stream->deferred_data != NULL &&
(stream->deferred_flags & NGHTTP2_DEFERRED_FLOW_CONTROL)) {
int r;
r = nghttp2_pq_push(&session->ob_pq, stream->deferred_data);
if(r == 0) {
nghttp2_stream_detach_deferred_data(stream);
} else if(r < 0) {
/* FATAL */
assert(r < NGHTTP2_ERR_FATAL);
return r;
}
}
nghttp2_session_call_on_frame_received(session, frame);
return 0;
}
if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment < if(NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
stream->remote_window_size) { stream->remote_window_size) {
int r; int r;

View File

@ -238,22 +238,10 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
{ {
int rv; int rv;
nghttp2_stream *stream; nghttp2_stream *stream;
flags &= NGHTTP2_FLAG_END_FLOW_CONTROL; if(window_size_increment == 0) {
if(flags & NGHTTP2_FLAG_END_FLOW_CONTROL) {
if(stream_id == 0) {
session->local_flow_control = 0;
} else {
stream = nghttp2_session_get_stream(session, stream_id);
if(stream) {
stream->local_flow_control = 0;
} else {
return NGHTTP2_ERR_STREAM_CLOSED;
}
}
return nghttp2_session_add_window_update(session, flags, stream_id, 0);
} else if(window_size_increment == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT; return NGHTTP2_ERR_INVALID_ARGUMENT;
} }
flags = 0;
if(stream_id == 0) { if(stream_id == 0) {
if(!session->local_flow_control) { if(!session->local_flow_control) {
return NGHTTP2_ERR_INVALID_ARGUMENT; return NGHTTP2_ERR_INVALID_ARGUMENT;

View File

@ -71,8 +71,7 @@ Config::Config()
data_ptr(nullptr), data_ptr(nullptr),
verify_client(false), verify_client(false),
no_tls(false), no_tls(false),
no_connection_flow_control(false), no_flow_control(false),
no_stream_flow_control(false),
output_upper_thres(1024*1024) output_upper_thres(1024*1024)
{} {}
@ -353,8 +352,7 @@ int Http2Handler::on_connect()
size_t niv = 1; size_t niv = 1;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = 100; entry[0].value = 100;
if(sessions_->get_config()->no_connection_flow_control && if(sessions_->get_config()->no_flow_control) {
sessions_->get_config()->no_stream_flow_control) {
entry[niv].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS; entry[niv].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
entry[niv].value = 1; entry[niv].value = 1;
++niv; ++niv;
@ -363,14 +361,6 @@ int Http2Handler::on_connect()
if(r != 0) { if(r != 0) {
return r; return r;
} }
if(sessions_->get_config()->no_connection_flow_control &&
!sessions_->get_config()->no_stream_flow_control) {
r = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_END_FLOW_CONTROL,
0, 0);
if(r != 0) {
return r;
}
}
return on_write(); return on_write();
} }
@ -717,11 +707,6 @@ void hd_on_frame_recv_callback
auto req = util::make_unique<Request>(stream_id); auto req = util::make_unique<Request>(stream_id);
append_nv(req.get(), frame->headers.nva, frame->headers.nvlen); append_nv(req.get(), frame->headers.nva, frame->headers.nvlen);
hd->add_stream(stream_id, std::move(req)); hd->add_stream(stream_id, std::move(req));
if(!hd->get_config()->no_connection_flow_control &&
hd->get_config()->no_stream_flow_control) {
nghttp2_submit_window_update(session, NGHTTP2_FLAG_END_FLOW_CONTROL,
stream_id, 0);
}
break; break;
} }
case NGHTTP2_HCAT_HEADERS: case NGHTTP2_HCAT_HEADERS:

View File

@ -57,8 +57,7 @@ struct Config {
void *data_ptr; void *data_ptr;
bool verify_client; bool verify_client;
bool no_tls; bool no_tls;
bool no_connection_flow_control; bool no_flow_control;
bool no_stream_flow_control;
size_t output_upper_thres; size_t output_upper_thres;
Config(); Config();
}; };

View File

@ -217,11 +217,6 @@ void print_flags(const nghttp2_frame_hd& hd)
s += "PONG"; s += "PONG";
} }
break; break;
case NGHTTP2_WINDOW_UPDATE:
if(hd.flags & NGHTTP2_FLAG_END_FLOW_CONTROL) {
s += "END_FLOW_CONTROL";
}
break;
} }
printf("; %s\n", s.c_str()); printf("; %s\n", s.c_str());
} }

View File

@ -79,8 +79,7 @@ struct Config {
bool verbose; bool verbose;
bool get_assets; bool get_assets;
bool stat; bool stat;
bool no_connection_flow_control; bool no_flow_control;
bool no_stream_flow_control;
bool upgrade; bool upgrade;
int32_t pri; int32_t pri;
int multiply; int multiply;
@ -98,8 +97,7 @@ struct Config {
verbose(false), verbose(false),
get_assets(false), get_assets(false),
stat(false), stat(false),
no_connection_flow_control(false), no_flow_control(false),
no_stream_flow_control(false),
upgrade(false), upgrade(false),
pri(NGHTTP2_PRI_DEFAULT), pri(NGHTTP2_PRI_DEFAULT),
multiply(1), multiply(1),
@ -334,7 +332,7 @@ size_t populate_settings(nghttp2_settings_entry *iv)
} else { } else {
iv[1].value = NGHTTP2_INITIAL_WINDOW_SIZE; iv[1].value = NGHTTP2_INITIAL_WINDOW_SIZE;
} }
if(config.no_connection_flow_control && config.no_stream_flow_control) { if(config.no_flow_control) {
iv[niv].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS; iv[niv].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
iv[niv].value = 1; iv[niv].value = 1;
++niv; ++niv;
@ -653,13 +651,6 @@ struct HttpClient {
return -1; return -1;
} }
} }
if(config.no_connection_flow_control && !config.no_stream_flow_control) {
rv = nghttp2_submit_window_update(session, NGHTTP2_FLAG_END_FLOW_CONTROL,
0, 0);
if(rv != 0) {
return -1;
}
}
// Adjust first request depending on the existence of the upload // Adjust first request depending on the existence of the upload
// data // data
for(auto i = std::begin(reqvec)+(need_upgrade() && !reqvec[0]->data_prd); for(auto i = std::begin(reqvec)+(need_upgrade() && !reqvec[0]->data_prd);
@ -983,12 +974,6 @@ void check_stream_id(nghttp2_session *session, int32_t stream_id,
stream_id); stream_id);
client->streams[stream_id] = req; client->streams[stream_id] = req;
req->record_syn_stream_time(); req->record_syn_stream_time();
if(!config.no_connection_flow_control && config.no_stream_flow_control) {
nghttp2_submit_window_update(session,
NGHTTP2_FLAG_END_FLOW_CONTROL,
stream_id, 0);
}
} }
} // namespace } // namespace
@ -1421,7 +1406,7 @@ int run(char **uris, int n)
void print_usage(std::ostream& out) void print_usage(std::ostream& out)
{ {
out << "Usage: nghttp [-FOafnsuv] [-t <SECONDS>] [-w <WINDOW_BITS>] [--cert=<CERT>]\n" out << "Usage: nghttp [-Oafnsuv] [-t <SECONDS>] [-w <WINDOW_BITS>] [--cert=<CERT>]\n"
<< " [--key=<KEY>] [-d <FILE>] [-m <N>] [-p <PRIORITY>]\n" << " [--key=<KEY>] [-d <FILE>] [-m <N>] [-p <PRIORITY>]\n"
<< " <URI>..." << " <URI>..."
<< std::endl; << std::endl;
@ -1458,10 +1443,9 @@ void print_help(std::ostream& out)
<< " -m, --multiply=<N> Request each URI <N> times. By default, same\n" << " -m, --multiply=<N> Request each URI <N> times. By default, same\n"
<< " URI is not requested twice. This option\n" << " URI is not requested twice. This option\n"
<< " disables it too.\n" << " disables it too.\n"
<< " -F, --no-connection-flow-control\n" << " -f, --no-low-control\n"
<< " Disables connection level flow control.\n" << " Disables connection and stream level flow\n"
<< " -f, --no-stream-flow-control\n" << " controls.\n"
<< " Disables stream level flow control.\n"
<< " -u, --upgrade Perform HTTP Upgrade for HTTP/2.0. This\n" << " -u, --upgrade Perform HTTP Upgrade for HTTP/2.0. This\n"
<< " option is ignored if the request URI has\n" << " option is ignored if the request URI has\n"
<< " https scheme.\n" << " https scheme.\n"
@ -1491,27 +1475,23 @@ int main(int argc, char **argv)
{"header", required_argument, 0, 'H' }, {"header", required_argument, 0, 'H' },
{"data", required_argument, 0, 'd' }, {"data", required_argument, 0, 'd' },
{"multiply", required_argument, 0, 'm' }, {"multiply", required_argument, 0, 'm' },
{"no-connection-flow-control", no_argument, 0, 'F'}, {"no-flow-control", no_argument, 0, 'f'},
{"no-stream-flow-control", no_argument, 0, 'f'},
{"upgrade", no_argument, 0, 'u'}, {"upgrade", no_argument, 0, 'u'},
{"pri", required_argument, 0, 'p'}, {"pri", required_argument, 0, 'p'},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
int option_index = 0; int option_index = 0;
int c = getopt_long(argc, argv, "FOad:fm:np:hH:vst:uw:", long_options, int c = getopt_long(argc, argv, "Oad:fm:np:hH:vst:uw:", long_options,
&option_index); &option_index);
if(c == -1) { if(c == -1) {
break; break;
} }
switch(c) { switch(c) {
case 'F':
config.no_connection_flow_control = true;
break;
case 'O': case 'O':
config.remote_name = true; config.remote_name = true;
break; break;
case 'f': case 'f':
config.no_stream_flow_control = true; config.no_flow_control = true;
break; break;
case 'h': case 'h':
print_help(std::cout); print_help(std::cout);

View File

@ -45,7 +45,7 @@ namespace nghttp2 {
namespace { namespace {
void print_usage(std::ostream& out) void print_usage(std::ostream& out)
{ {
out << "Usage: nghttpd [-FDVfhv] [-d <PATH>] [--no-tls] <PORT> [<PRIVATE_KEY> <CERT>]" out << "Usage: nghttpd [-DVfhv] [-d <PATH>] [--no-tls] <PORT> [<PRIVATE_KEY> <CERT>]"
<< std::endl; << std::endl;
} }
} // namespace } // namespace
@ -73,10 +73,9 @@ void print_help(std::ostream& out)
<< " -v, --verbose Print debug information such as reception/\n" << " -v, --verbose Print debug information such as reception/\n"
<< " transmission of frames and name/value pairs.\n" << " transmission of frames and name/value pairs.\n"
<< " --no-tls Disable SSL/TLS.\n" << " --no-tls Disable SSL/TLS.\n"
<< " -F, --no-connection-flow-control\n" << " -f, --no-flow-control\n"
<< " Disables connection level flow control.\n" << " Disables connection and stream level flow\n"
<< " -f, --no-stream-flow-control\n" << " controls.\n"
<< " Disables stream level flow control.\n"
<< " -h, --help Print this help.\n" << " -h, --help Print this help.\n"
<< std::endl; << std::endl;
} }
@ -94,19 +93,15 @@ int main(int argc, char **argv)
{"verbose", no_argument, 0, 'v' }, {"verbose", no_argument, 0, 'v' },
{"verify-client", no_argument, 0, 'V' }, {"verify-client", no_argument, 0, 'V' },
{"no-tls", no_argument, &flag, 1 }, {"no-tls", no_argument, &flag, 1 },
{"no-connection-flow-control", no_argument, 0, 'F'}, {"no-flow-control", no_argument, 0, 'f'},
{"no-stream-flow-control", no_argument, 0, 'f'},
{0, 0, 0, 0 } {0, 0, 0, 0 }
}; };
int option_index = 0; int option_index = 0;
int c = getopt_long(argc, argv, "FDVd:fhv", long_options, &option_index); int c = getopt_long(argc, argv, "DVd:fhv", long_options, &option_index);
if(c == -1) { if(c == -1) {
break; break;
} }
switch(c) { switch(c) {
case 'F':
config.no_connection_flow_control = true;
break;
case 'D': case 'D':
config.daemon = true; config.daemon = true;
break; break;
@ -117,7 +112,7 @@ int main(int argc, char **argv)
config.htdocs = optarg; config.htdocs = optarg;
break; break;
case 'f': case 'f':
config.no_stream_flow_control = true; config.no_flow_control = true;
break; break;
case 'h': case 'h':
print_help(std::cout); print_help(std::cout);

View File

@ -368,7 +368,7 @@ void test_nghttp2_frame_pack_window_update(void)
uint8_t *buf = NULL; uint8_t *buf = NULL;
size_t buflen = 0; size_t buflen = 0;
ssize_t framelen; ssize_t framelen;
nghttp2_frame_window_update_init(&frame, NGHTTP2_FLAG_END_FLOW_CONTROL, nghttp2_frame_window_update_init(&frame, NGHTTP2_FLAG_NONE,
1000000007, 4096); 1000000007, 4096);
framelen = nghttp2_frame_pack_window_update(&buf, &buflen, framelen = nghttp2_frame_pack_window_update(&buf, &buflen,
&frame); &frame);
@ -377,7 +377,7 @@ void test_nghttp2_frame_pack_window_update(void)
&buf[0], NGHTTP2_FRAME_HEAD_LENGTH, &buf[0], NGHTTP2_FRAME_HEAD_LENGTH,
&buf[NGHTTP2_FRAME_HEAD_LENGTH], &buf[NGHTTP2_FRAME_HEAD_LENGTH],
framelen - NGHTTP2_FRAME_HEAD_LENGTH)); framelen - NGHTTP2_FRAME_HEAD_LENGTH));
check_frame_header(4, NGHTTP2_WINDOW_UPDATE, NGHTTP2_FLAG_END_FLOW_CONTROL, check_frame_header(4, NGHTTP2_WINDOW_UPDATE, NGHTTP2_FLAG_NONE,
1000000007, &oframe.hd); 1000000007, &oframe.hd);
CU_ASSERT(4096 == oframe.window_size_increment); CU_ASSERT(4096 == oframe.window_size_increment);
free(buf); free(buf);

View File

@ -1158,25 +1158,6 @@ void test_nghttp2_session_on_window_update_received(void)
nghttp2_frame_window_update_free(&frame.window_update); nghttp2_frame_window_update_free(&frame.window_update);
/* Check END_FLOW_CONTROL flag */
user_data.frame_recv_cb_called = 0;
nghttp2_frame_window_update_init(&frame.window_update,
NGHTTP2_FLAG_END_FLOW_CONTROL, 1, 0);
CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
CU_ASSERT(1 == user_data.frame_recv_cb_called);
CU_ASSERT(0 == stream->remote_flow_control);
nghttp2_frame_window_update_free(&frame.window_update);
user_data.frame_recv_cb_called = 0;
nghttp2_frame_window_update_init(&frame.window_update,
NGHTTP2_FLAG_END_FLOW_CONTROL, 0, 0);
CU_ASSERT(0 == nghttp2_session_on_window_update_received(session, &frame));
CU_ASSERT(1 == user_data.frame_recv_cb_called);
CU_ASSERT(0 == session->remote_flow_control);
nghttp2_frame_window_update_free(&frame.window_update);
nghttp2_session_del(session); nghttp2_session_del(session);
} }
@ -2114,23 +2095,10 @@ void test_nghttp2_submit_window_update(void)
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == stream->recv_window_size); CU_ASSERT(0 == stream->recv_window_size);
/* Disable stream-level flow control */
CU_ASSERT(0 == nghttp2_submit_window_update(session,
NGHTTP2_FLAG_END_FLOW_CONTROL,
2, 0));
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == stream->local_flow_control);
/* Disable connection-level flow control */
CU_ASSERT(0 == nghttp2_submit_window_update(session,
NGHTTP2_FLAG_END_FLOW_CONTROL,
0, 0));
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == session->local_flow_control);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0)); nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, 0));
/* Disable local flow control */
stream->local_flow_control = 0;
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, -1)); nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, -1));
CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED ==
@ -2734,6 +2702,7 @@ void test_nghttp2_session_flow_control_disable_remote(void)
nghttp2_data_provider data_prd; nghttp2_data_provider data_prd;
nghttp2_frame frame; nghttp2_frame frame;
size_t data_size = 128*1024; size_t data_size = 128*1024;
nghttp2_settings_entry iv = { NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS, 0x1 };
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback; callbacks.send_callback = null_send_callback;
@ -2751,31 +2720,20 @@ void test_nghttp2_session_flow_control_disable_remote(void)
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length); CU_ASSERT(data_size - NGHTTP2_INITIAL_WINDOW_SIZE == ud.data_source_length);
/* Disable stream flow control */ /* Disable flow control entirely */
nghttp2_frame_window_update_init(&frame.window_update, nghttp2_frame_settings_init(&frame.settings, dup_iv(&iv, 1), 1);
NGHTTP2_FLAG_END_FLOW_CONTROL, 1, 0); nghttp2_session_on_settings_received(session, &frame);
nghttp2_session_on_window_update_received(session, &frame);
/* Check stream-level remote_flow_control is disabled */ /* Check both connection and stream-level remote_flow_control is
disabled */
CU_ASSERT(0 == nghttp2_session_get_stream(session, 1)->remote_flow_control); CU_ASSERT(0 == nghttp2_session_get_stream(session, 1)->remote_flow_control);
/* Still nothing is sent because of connection-level flow control */
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(data_size - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ==
ud.data_source_length);
/* Disable connection-level flow control */
frame.hd.stream_id = 0;
nghttp2_session_on_window_update_received(session, &frame);
/* Check connection-level remote_flow_control is disabled */
CU_ASSERT(0 == session->remote_flow_control); CU_ASSERT(0 == session->remote_flow_control);
/* Sends remaining data */ /* Sends remaining data */
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == ud.data_source_length); CU_ASSERT(0 == ud.data_source_length);
nghttp2_frame_window_update_free(&frame.window_update); nghttp2_frame_settings_free(&frame.settings);
nghttp2_session_del(session); nghttp2_session_del(session);
} }