Remove per-frame compression
This commit is contained in:
parent
b8ed74c1ec
commit
3db8935e20
|
@ -487,11 +487,7 @@ typedef enum {
|
||||||
/**
|
/**
|
||||||
* The PRIORITY flag.
|
* The PRIORITY flag.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_FLAG_PRIORITY = 0x20,
|
NGHTTP2_FLAG_PRIORITY = 0x20
|
||||||
/**
|
|
||||||
* THE COMPRESSED flag.
|
|
||||||
*/
|
|
||||||
NGHTTP2_FLAG_COMPRESSED = 0x20
|
|
||||||
} nghttp2_flag;
|
} nghttp2_flag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -515,14 +511,10 @@ typedef enum {
|
||||||
* SETTINGS_INITIAL_WINDOW_SIZE
|
* SETTINGS_INITIAL_WINDOW_SIZE
|
||||||
*/
|
*/
|
||||||
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4,
|
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4,
|
||||||
/**
|
|
||||||
* SETTINGS_COMPRESS_DATA
|
|
||||||
*/
|
|
||||||
NGHTTP2_SETTINGS_COMPRESS_DATA = 5,
|
|
||||||
/**
|
/**
|
||||||
* Maximum ID of :type:`nghttp2_settings_id`.
|
* Maximum ID of :type:`nghttp2_settings_id`.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_SETTINGS_MAX = 5
|
NGHTTP2_SETTINGS_MAX = 4
|
||||||
} nghttp2_settings_id;
|
} nghttp2_settings_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -645,11 +637,7 @@ typedef enum {
|
||||||
/**
|
/**
|
||||||
* Indicates EOF was sensed.
|
* Indicates EOF was sensed.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_DATA_FLAG_EOF = 0x01,
|
NGHTTP2_DATA_FLAG_EOF = 0x01
|
||||||
/**
|
|
||||||
* Indicates data was compressed by application.
|
|
||||||
*/
|
|
||||||
NGHTTP2_DATA_FLAG_COMPRESSED = 0x02
|
|
||||||
} nghttp2_data_flag;
|
} nghttp2_data_flag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -662,11 +650,6 @@ typedef enum {
|
||||||
* them in |buf| and return number of data stored in |buf|. If EOF is
|
* them in |buf| and return number of data stored in |buf|. If EOF is
|
||||||
* reached, set :enum:`NGHTTP2_DATA_FLAG_EOF` flag in |*data_flags|.
|
* reached, set :enum:`NGHTTP2_DATA_FLAG_EOF` flag in |*data_flags|.
|
||||||
*
|
*
|
||||||
* To send compressed data payload without affecting content-length,
|
|
||||||
* set :enum:`NGHTTP2_DATA_FLAG_COMPRESSED` flag in |*data_flags|.
|
|
||||||
* Compression must be done by application prior to fill data in
|
|
||||||
* |buf|.
|
|
||||||
*
|
|
||||||
* If the application wants to postpone DATA frames (e.g.,
|
* If the application wants to postpone DATA frames (e.g.,
|
||||||
* asynchronous I/O, or reading data blocks for long time), it is
|
* asynchronous I/O, or reading data blocks for long time), it is
|
||||||
* achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading
|
* achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading
|
||||||
|
|
|
@ -1022,7 +1022,6 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
|
||||||
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
|
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_SETTINGS_ENABLE_PUSH:
|
case NGHTTP2_SETTINGS_ENABLE_PUSH:
|
||||||
case NGHTTP2_SETTINGS_COMPRESS_DATA:
|
|
||||||
if(iv[i].value != 0 && iv[i].value != 1) {
|
if(iv[i].value != 0 && iv[i].value != 1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,7 +229,6 @@ static void init_settings(uint32_t *settings)
|
||||||
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
|
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
|
||||||
settings[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] =
|
settings[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] =
|
||||||
NGHTTP2_INITIAL_WINDOW_SIZE;
|
NGHTTP2_INITIAL_WINDOW_SIZE;
|
||||||
settings[NGHTTP2_SETTINGS_COMPRESS_DATA] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void active_outbound_item_reset(nghttp2_active_outbound_item *aob)
|
static void active_outbound_item_reset(nghttp2_active_outbound_item *aob)
|
||||||
|
@ -3423,12 +3422,6 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
|
||||||
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR);
|
(session, frame, NGHTTP2_FLOW_CONTROL_ERROR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_SETTINGS_COMPRESS_DATA:
|
|
||||||
if(entry->value != 0 && entry->value != 1) {
|
|
||||||
return session_handle_invalid_connection
|
|
||||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
session->remote_settings[entry->settings_id] = entry->value;
|
session->remote_settings[entry->settings_id] = entry->value;
|
||||||
}
|
}
|
||||||
|
@ -4013,11 +4006,6 @@ static int session_on_data_received_fail_fast(nghttp2_session *session)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((iframe->frame.hd.flags & NGHTTP2_FLAG_COMPRESSED) &&
|
|
||||||
session->local_settings[NGHTTP2_SETTINGS_COMPRESS_DATA] == 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nghttp2_session_is_my_stream_id(session, stream_id)) {
|
if(nghttp2_session_is_my_stream_id(session, stream_id)) {
|
||||||
if(stream->state == NGHTTP2_STREAM_CLOSING) {
|
if(stream->state == NGHTTP2_STREAM_CLOSING) {
|
||||||
return NGHTTP2_ERR_IGN_PAYLOAD;
|
return NGHTTP2_ERR_IGN_PAYLOAD;
|
||||||
|
@ -4088,7 +4076,6 @@ static int inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe)
|
||||||
case NGHTTP2_SETTINGS_ENABLE_PUSH:
|
case NGHTTP2_SETTINGS_ENABLE_PUSH:
|
||||||
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
|
case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
|
||||||
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
|
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
|
||||||
case NGHTTP2_SETTINGS_COMPRESS_DATA:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -4238,8 +4225,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
iframe->frame.hd.flags &= (NGHTTP2_FLAG_END_STREAM |
|
iframe->frame.hd.flags &= (NGHTTP2_FLAG_END_STREAM |
|
||||||
NGHTTP2_FLAG_END_SEGMENT |
|
NGHTTP2_FLAG_END_SEGMENT |
|
||||||
NGHTTP2_FLAG_PAD_LOW |
|
NGHTTP2_FLAG_PAD_LOW |
|
||||||
NGHTTP2_FLAG_PAD_HIGH |
|
NGHTTP2_FLAG_PAD_HIGH);
|
||||||
NGHTTP2_FLAG_COMPRESSED);
|
|
||||||
/* Check stream is open. If it is not open or closing,
|
/* Check stream is open. If it is not open or closing,
|
||||||
ignore payload. */
|
ignore payload. */
|
||||||
busy = 1;
|
busy = 1;
|
||||||
|
@ -5560,10 +5546,6 @@ int nghttp2_session_pack_data(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data_flags & NGHTTP2_DATA_FLAG_COMPRESSED) {
|
|
||||||
flags |= NGHTTP2_FLAG_COMPRESSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The primary reason of data_frame is pass to the user callback */
|
/* The primary reason of data_frame is pass to the user callback */
|
||||||
data_frame.hd.length = payloadlen;
|
data_frame.hd.length = payloadlen;
|
||||||
data_frame.hd.stream_id = frame->hd.stream_id;
|
data_frame.hd.stream_id = frame->hd.stream_id;
|
||||||
|
|
|
@ -120,8 +120,7 @@ Stream::Stream(Http2Handler *handler, int32_t stream_id)
|
||||||
rtimer(nullptr),
|
rtimer(nullptr),
|
||||||
wtimer(nullptr),
|
wtimer(nullptr),
|
||||||
stream_id(stream_id),
|
stream_id(stream_id),
|
||||||
file(-1),
|
file(-1)
|
||||||
enable_compression(false)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Stream::~Stream()
|
Stream::~Stream()
|
||||||
|
@ -726,12 +725,10 @@ int Http2Handler::on_connect()
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
nghttp2_settings_entry entry[4];
|
nghttp2_settings_entry entry[4];
|
||||||
size_t niv = 2;
|
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;
|
||||||
entry[1].settings_id = NGHTTP2_SETTINGS_COMPRESS_DATA;
|
|
||||||
entry[1].value = 1;
|
|
||||||
|
|
||||||
if(sessions_->get_config()->header_table_size >= 0) {
|
if(sessions_->get_config()->header_table_size >= 0) {
|
||||||
entry[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
entry[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
||||||
|
@ -949,19 +946,6 @@ void Http2Handler::terminate_session(nghttp2_error_code error_code)
|
||||||
nghttp2_session_terminate_session(session_, error_code);
|
nghttp2_session_terminate_session(session_, error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Handler::decide_compression(const std::string& path, Stream *stream)
|
|
||||||
{
|
|
||||||
if(nghttp2_session_get_remote_settings
|
|
||||||
(session_, NGHTTP2_SETTINGS_COMPRESS_DATA) == 1 &&
|
|
||||||
(util::endsWith(path, ".html") ||
|
|
||||||
util::endsWith(path, ".js") ||
|
|
||||||
util::endsWith(path, ".css") ||
|
|
||||||
util::endsWith(path, ".txt"))) {
|
|
||||||
|
|
||||||
stream->enable_compression = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t file_read_callback
|
ssize_t file_read_callback
|
||||||
(nghttp2_session *session, int32_t stream_id,
|
(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t length, uint32_t *data_flags,
|
uint8_t *buf, size_t length, uint32_t *data_flags,
|
||||||
|
@ -972,36 +956,9 @@ ssize_t file_read_callback
|
||||||
|
|
||||||
int fd = source->fd;
|
int fd = source->fd;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
ssize_t rv;
|
|
||||||
|
|
||||||
// Compressing too small data is not efficient?
|
|
||||||
if(length >= 1024 && stream && stream->enable_compression) {
|
|
||||||
uint8_t srcbuf[4096];
|
|
||||||
auto maxread = std::min(length, sizeof(srcbuf));
|
|
||||||
|
|
||||||
while((nread = read(fd, srcbuf, maxread)) == -1 && errno == EINTR);
|
|
||||||
if(nread == -1) {
|
|
||||||
if(stream) {
|
|
||||||
remove_stream_read_timeout(stream);
|
|
||||||
remove_stream_write_timeout(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nread > 0) {
|
|
||||||
rv = deflate_data(buf, length, srcbuf, nread);
|
|
||||||
|
|
||||||
if(rv < 0) {
|
|
||||||
memcpy(buf, srcbuf, nread);
|
|
||||||
} else {
|
|
||||||
nread = rv;
|
|
||||||
|
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_COMPRESSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while((nread = read(fd, buf, length)) == -1 && errno == EINTR);
|
while((nread = read(fd, buf, length)) == -1 && errno == EINTR);
|
||||||
|
|
||||||
if(nread == -1) {
|
if(nread == -1) {
|
||||||
if(stream) {
|
if(stream) {
|
||||||
remove_stream_read_timeout(stream);
|
remove_stream_read_timeout(stream);
|
||||||
|
@ -1010,7 +967,6 @@ ssize_t file_read_callback
|
||||||
|
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(nread == 0) {
|
if(nread == 0) {
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||||
|
@ -1125,26 +1081,34 @@ void prepare_response(Stream *stream, Http2Handler *hd, bool allow_push = true)
|
||||||
int file = open(path.c_str(), O_RDONLY | O_BINARY);
|
int file = open(path.c_str(), O_RDONLY | O_BINARY);
|
||||||
if(file == -1) {
|
if(file == -1) {
|
||||||
prepare_status_response(stream, hd, STATUS_404);
|
prepare_status_response(stream, hd, STATUS_404);
|
||||||
} else {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
if(fstat(file, &buf) == -1) {
|
if(fstat(file, &buf) == -1) {
|
||||||
close(file);
|
close(file);
|
||||||
prepare_status_response(stream, hd, STATUS_404);
|
prepare_status_response(stream, hd, STATUS_404);
|
||||||
} else {
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
stream->file = file;
|
stream->file = file;
|
||||||
|
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider data_prd;
|
||||||
|
|
||||||
data_prd.source.fd = file;
|
data_prd.source.fd = file;
|
||||||
data_prd.read_callback = file_read_callback;
|
data_prd.read_callback = file_read_callback;
|
||||||
|
|
||||||
if(last_mod_found && buf.st_mtime <= last_mod) {
|
if(last_mod_found && buf.st_mtime <= last_mod) {
|
||||||
prepare_status_response(stream, hd, STATUS_304);
|
prepare_status_response(stream, hd, STATUS_304);
|
||||||
} else {
|
|
||||||
hd->decide_compression(path, stream);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
hd->submit_file_response(STATUS_200, stream, buf.st_mtime,
|
hd->submit_file_response(STATUS_200, stream, buf.st_mtime,
|
||||||
buf.st_size, &data_prd);
|
buf.st_size, &data_prd);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,6 @@ struct Stream {
|
||||||
event *wtimer;
|
event *wtimer;
|
||||||
int32_t stream_id;
|
int32_t stream_id;
|
||||||
int file;
|
int file;
|
||||||
bool enable_compression;
|
|
||||||
Stream(Http2Handler *handler, int32_t stream_id);
|
Stream(Http2Handler *handler, int32_t stream_id);
|
||||||
~Stream();
|
~Stream();
|
||||||
};
|
};
|
||||||
|
@ -140,7 +139,6 @@ public:
|
||||||
void remove_settings_timer();
|
void remove_settings_timer();
|
||||||
void terminate_session(nghttp2_error_code error_code);
|
void terminate_session(nghttp2_error_code error_code);
|
||||||
int tls_handshake();
|
int tls_handshake();
|
||||||
void decide_compression(const std::string& path, Stream *stream);
|
|
||||||
private:
|
private:
|
||||||
int handle_ssl_temporal_error(int err);
|
int handle_ssl_temporal_error(int err);
|
||||||
int tls_write(const uint8_t *data, size_t datalen);
|
int tls_write(const uint8_t *data, size_t datalen);
|
||||||
|
|
|
@ -99,8 +99,6 @@ const char* strsettingsid(int32_t id)
|
||||||
return "SETTINGS_MAX_CONCURRENT_STREAMS";
|
return "SETTINGS_MAX_CONCURRENT_STREAMS";
|
||||||
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
|
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
|
||||||
return "SETTINGS_INITIAL_WINDOW_SIZE";
|
return "SETTINGS_INITIAL_WINDOW_SIZE";
|
||||||
case NGHTTP2_SETTINGS_COMPRESS_DATA:
|
|
||||||
return "SETTINGS_COMPRESS_DATA";
|
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
@ -243,12 +241,6 @@ void print_flags(const nghttp2_frame_hd& hd)
|
||||||
}
|
}
|
||||||
s += "PAD_HIGH";
|
s += "PAD_HIGH";
|
||||||
}
|
}
|
||||||
if(hd.flags & NGHTTP2_FLAG_COMPRESSED) {
|
|
||||||
if(!s.empty()) {
|
|
||||||
s += " | ";
|
|
||||||
}
|
|
||||||
s += "COMPRESSED";
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_HEADERS:
|
case NGHTTP2_HEADERS:
|
||||||
if(hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
if(hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
||||||
|
|
120
src/nghttp.cc
120
src/nghttp.cc
|
@ -100,7 +100,7 @@ struct Config {
|
||||||
bool stat;
|
bool stat;
|
||||||
bool upgrade;
|
bool upgrade;
|
||||||
bool continuation;
|
bool continuation;
|
||||||
bool compress_data;
|
|
||||||
Config()
|
Config()
|
||||||
: output_upper_thres(1024*1024),
|
: output_upper_thres(1024*1024),
|
||||||
padding(0),
|
padding(0),
|
||||||
|
@ -117,8 +117,7 @@ struct Config {
|
||||||
get_assets(false),
|
get_assets(false),
|
||||||
stat(false),
|
stat(false),
|
||||||
upgrade(false),
|
upgrade(false),
|
||||||
continuation(false),
|
continuation(false)
|
||||||
compress_data(false)
|
|
||||||
{
|
{
|
||||||
nghttp2_option_new(&http2_option);
|
nghttp2_option_new(&http2_option);
|
||||||
nghttp2_option_set_peer_max_concurrent_streams
|
nghttp2_option_set_peer_max_concurrent_streams
|
||||||
|
@ -347,7 +346,7 @@ Config config;
|
||||||
namespace {
|
namespace {
|
||||||
size_t populate_settings(nghttp2_settings_entry *iv)
|
size_t populate_settings(nghttp2_settings_entry *iv)
|
||||||
{
|
{
|
||||||
size_t niv = 3;
|
size_t niv = 2;
|
||||||
|
|
||||||
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||||
iv[0].value = 100;
|
iv[0].value = 100;
|
||||||
|
@ -359,9 +358,6 @@ size_t populate_settings(nghttp2_settings_entry *iv)
|
||||||
iv[1].value = NGHTTP2_INITIAL_WINDOW_SIZE;
|
iv[1].value = NGHTTP2_INITIAL_WINDOW_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
iv[2].settings_id = NGHTTP2_SETTINGS_COMPRESS_DATA;
|
|
||||||
iv[2].value = 1;
|
|
||||||
|
|
||||||
if(config.header_table_size >= 0) {
|
if(config.header_table_size >= 0) {
|
||||||
iv[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
iv[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
||||||
iv[niv].value = config.header_table_size;
|
iv[niv].value = config.header_table_size;
|
||||||
|
@ -1184,65 +1180,15 @@ int on_data_chunk_recv_callback
|
||||||
data += tlen;
|
data += tlen;
|
||||||
len -= tlen;
|
len -= tlen;
|
||||||
}
|
}
|
||||||
} else if(flags & NGHTTP2_FLAG_COMPRESSED) {
|
|
||||||
if(len == 0 || !client->check_inflater(stream_id)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t MAX_OUTLEN = 4096;
|
|
||||||
uint8_t out[MAX_OUTLEN];
|
|
||||||
size_t outlen;
|
|
||||||
|
|
||||||
do {
|
|
||||||
outlen = MAX_OUTLEN;
|
|
||||||
auto tlen = len;
|
|
||||||
|
|
||||||
int rv = nghttp2_gzip_inflate(client->inflater, out, &outlen,
|
|
||||||
data, &tlen);
|
|
||||||
if(rv != 0) {
|
|
||||||
goto per_frame_decomp_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!config.null_out) {
|
|
||||||
std::cout.write(reinterpret_cast<const char*>(out), outlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_html_parser(client, req, out, outlen, 0);
|
|
||||||
|
|
||||||
data += tlen;
|
|
||||||
len -= tlen;
|
|
||||||
|
|
||||||
if(nghttp2_gzip_inflate_finished(client->inflater)) {
|
|
||||||
// When Z_STREAM_END was reached, remaining input length
|
|
||||||
// must be 0.
|
|
||||||
if(len > 0) {
|
|
||||||
goto per_frame_decomp_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while(len > 0 || outlen > 0);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if(!config.null_out) {
|
if(!config.null_out) {
|
||||||
std::cout.write(reinterpret_cast<const char*>(data), len);
|
std::cout.write(reinterpret_cast<const char*>(data), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_html_parser(client, req, data, len, 0);
|
update_html_parser(client, req, data, len, 0);
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
per_frame_decomp_error:
|
|
||||||
// If per-frame decompression failed, we remember the stream ID so
|
|
||||||
// that subsequent chunk of DATA is ignored.
|
|
||||||
client->last_inflate_error_stream_id = stream_id;
|
|
||||||
|
|
||||||
if(!client->reset_inflater()) {
|
|
||||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
|
|
||||||
NGHTTP2_INTERNAL_ERROR);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1379,28 +1325,6 @@ int on_frame_recv_callback2
|
||||||
|
|
||||||
auto client = get_session(user_data);
|
auto client = get_session(user_data);
|
||||||
switch(frame->hd.type) {
|
switch(frame->hd.type) {
|
||||||
case NGHTTP2_DATA:
|
|
||||||
if(frame->hd.flags & NGHTTP2_FLAG_COMPRESSED) {
|
|
||||||
|
|
||||||
auto inflate_finished = nghttp2_gzip_inflate_finished(client->inflater);
|
|
||||||
|
|
||||||
if(!client->reset_inflater()) {
|
|
||||||
rv = nghttp2_session_terminate_session(session,
|
|
||||||
NGHTTP2_INTERNAL_ERROR);
|
|
||||||
|
|
||||||
if(nghttp2_is_fatal(rv)) {
|
|
||||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
|
||||||
} else {
|
|
||||||
rv = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Error if compressed block does not end in frame.
|
|
||||||
if(!inflate_finished) {
|
|
||||||
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
|
||||||
frame->hd.stream_id, NGHTTP2_PROTOCOL_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NGHTTP2_HEADERS: {
|
case NGHTTP2_HEADERS: {
|
||||||
if(frame->headers.cat != NGHTTP2_HCAT_RESPONSE &&
|
if(frame->headers.cat != NGHTTP2_HCAT_RESPONSE &&
|
||||||
frame->headers.cat != NGHTTP2_HCAT_PUSH_RESPONSE) {
|
frame->headers.cat != NGHTTP2_HCAT_PUSH_RESPONSE) {
|
||||||
|
@ -1820,38 +1744,13 @@ ssize_t file_read_callback
|
||||||
assert(req);
|
assert(req);
|
||||||
int fd = source->fd;
|
int fd = source->fd;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
ssize_t rv;
|
|
||||||
|
|
||||||
// Compressing too small data is not efficient?
|
|
||||||
if(length >= 1024 && config.compress_data &&
|
|
||||||
nghttp2_session_get_remote_settings
|
|
||||||
(session, NGHTTP2_SETTINGS_COMPRESS_DATA) == 1) {
|
|
||||||
uint8_t srcbuf[4096];
|
|
||||||
auto maxread = std::min(length, sizeof(srcbuf));
|
|
||||||
|
|
||||||
while((nread = read(fd, srcbuf, maxread)) == -1 && errno == EINTR);
|
|
||||||
if(nread == -1) {
|
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nread > 0) {
|
|
||||||
rv = deflate_data(buf, length, srcbuf, nread);
|
|
||||||
|
|
||||||
if(rv < 0) {
|
|
||||||
memcpy(buf, srcbuf, nread);
|
|
||||||
} else {
|
|
||||||
nread = rv;
|
|
||||||
|
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_COMPRESSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while((nread = pread(fd, buf, length, req->data_offset)) == -1 &&
|
while((nread = pread(fd, buf, length, req->data_offset)) == -1 &&
|
||||||
errno == EINTR);
|
errno == EINTR);
|
||||||
|
|
||||||
if(nread == -1) {
|
if(nread == -1) {
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(nread == 0) {
|
if(nread == 0) {
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||||
|
@ -1992,9 +1891,6 @@ Options:
|
||||||
be in PEM format.
|
be in PEM format.
|
||||||
-d, --data=<FILE> Post FILE to server. If '-' is given, data will
|
-d, --data=<FILE> Post FILE to server. If '-' is given, data will
|
||||||
be read from stdin.
|
be read from stdin.
|
||||||
-g, --compress-data
|
|
||||||
When used with -d option, compress request body
|
|
||||||
on the fly using per-frame compression.
|
|
||||||
-m, --multiply=<N> Request each URI <N> times. By default, same URI
|
-m, --multiply=<N> Request each URI <N> times. By default, same URI
|
||||||
is not requested twice. This option disables it
|
is not requested twice. This option disables it
|
||||||
too.
|
too.
|
||||||
|
@ -2042,7 +1938,6 @@ int main(int argc, char **argv)
|
||||||
{"help", no_argument, nullptr, 'h'},
|
{"help", no_argument, nullptr, 'h'},
|
||||||
{"header", required_argument, nullptr, 'H'},
|
{"header", required_argument, nullptr, 'H'},
|
||||||
{"data", required_argument, nullptr, 'd'},
|
{"data", required_argument, nullptr, 'd'},
|
||||||
{"compress-data", no_argument, nullptr, 'g'},
|
|
||||||
{"multiply", required_argument, nullptr, 'm'},
|
{"multiply", required_argument, nullptr, 'm'},
|
||||||
{"upgrade", no_argument, nullptr, 'u'},
|
{"upgrade", no_argument, nullptr, 'u'},
|
||||||
{"weight", required_argument, nullptr, 'p'},
|
{"weight", required_argument, nullptr, 'p'},
|
||||||
|
@ -2162,9 +2057,6 @@ int main(int argc, char **argv)
|
||||||
case 'd':
|
case 'd':
|
||||||
config.datafile = strcmp("-", optarg) == 0 ? "/dev/stdin" : optarg;
|
config.datafile = strcmp("-", optarg) == 0 ? "/dev/stdin" : optarg;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
|
||||||
config.compress_data = true;
|
|
||||||
break;
|
|
||||||
case 'm':
|
case 'm':
|
||||||
config.multiply = strtoul(optarg, nullptr, 10);
|
config.multiply = strtoul(optarg, nullptr, 10);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -634,15 +634,6 @@ void test_nghttp2_iv_check(void)
|
||||||
iv[1].value = 3;
|
iv[1].value = 3;
|
||||||
CU_ASSERT(!nghttp2_iv_check(iv, 2));
|
CU_ASSERT(!nghttp2_iv_check(iv, 2));
|
||||||
|
|
||||||
/* COMPRESSED_DATA only allows 0 or 1 */
|
|
||||||
iv[1].settings_id = NGHTTP2_SETTINGS_COMPRESS_DATA;
|
|
||||||
iv[1].value = 0;
|
|
||||||
CU_ASSERT(nghttp2_iv_check(iv, 2));
|
|
||||||
iv[1].value = 1;
|
|
||||||
CU_ASSERT(nghttp2_iv_check(iv, 2));
|
|
||||||
iv[1].value = 3;
|
|
||||||
CU_ASSERT(!nghttp2_iv_check(iv, 2));
|
|
||||||
|
|
||||||
/* Undefined SETTINGS ID */
|
/* Undefined SETTINGS ID */
|
||||||
iv[1].settings_id = 1000000009;
|
iv[1].settings_id = 1000000009;
|
||||||
iv[1].value = 0;
|
iv[1].value = 0;
|
||||||
|
|
|
@ -75,7 +75,6 @@ typedef struct {
|
||||||
nghttp2_nv nv;
|
nghttp2_nv nv;
|
||||||
size_t data_chunk_len;
|
size_t data_chunk_len;
|
||||||
size_t padding_boundary;
|
size_t padding_boundary;
|
||||||
int compress_data;
|
|
||||||
} my_user_data;
|
} my_user_data;
|
||||||
|
|
||||||
static void scripted_data_feed_init2(scripted_data_feed *df,
|
static void scripted_data_feed_init2(scripted_data_feed *df,
|
||||||
|
@ -250,24 +249,6 @@ static ssize_t fixed_length_data_source_read_callback
|
||||||
return wlen;
|
return wlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t compressed_fixed_length_data_source_read_callback
|
|
||||||
(nghttp2_session *session, int32_t stream_id,
|
|
||||||
uint8_t *buf, size_t len, uint32_t *data_flags,
|
|
||||||
nghttp2_data_source *source, void *user_data)
|
|
||||||
{
|
|
||||||
my_user_data *ud = (my_user_data*)user_data;
|
|
||||||
size_t wlen;
|
|
||||||
|
|
||||||
wlen = fixed_length_data_source_read_callback
|
|
||||||
(session, stream_id, buf, len, data_flags, source, user_data);
|
|
||||||
|
|
||||||
if(ud->compress_data) {
|
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_COMPRESSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t temporal_failure_data_source_read_callback
|
static ssize_t temporal_failure_data_source_read_callback
|
||||||
(nghttp2_session *session, int32_t stream_id,
|
(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t len, uint32_t *data_flags,
|
uint8_t *buf, size_t len, uint32_t *data_flags,
|
||||||
|
@ -722,57 +703,6 @@ void test_nghttp2_session_recv_data(void)
|
||||||
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
|
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
|
|
||||||
/* Receiving compressed DATA while SETTINGS_COMPRESS_DATA == 0 is
|
|
||||||
subject to connection error */
|
|
||||||
|
|
||||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
|
||||||
|
|
||||||
hd.length = 4096;
|
|
||||||
hd.type = NGHTTP2_DATA;
|
|
||||||
hd.flags = NGHTTP2_FLAG_COMPRESSED;
|
|
||||||
hd.stream_id = 1;
|
|
||||||
nghttp2_frame_pack_frame_hd(data, &hd);
|
|
||||||
|
|
||||||
stream = nghttp2_session_open_stream(session, 1,
|
|
||||||
NGHTTP2_STREAM_FLAG_NONE,
|
|
||||||
&pri_spec_default,
|
|
||||||
NGHTTP2_STREAM_OPENED, NULL);
|
|
||||||
|
|
||||||
ud.data_chunk_recv_cb_called = 0;
|
|
||||||
ud.frame_recv_cb_called = 0;
|
|
||||||
rv = nghttp2_session_mem_recv(session, data, 8+4096);
|
|
||||||
CU_ASSERT(8+4096 == rv);
|
|
||||||
|
|
||||||
CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
|
|
||||||
CU_ASSERT(0 == ud.frame_recv_cb_called);
|
|
||||||
item = nghttp2_session_get_next_ob_item(session);
|
|
||||||
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
|
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
|
||||||
|
|
||||||
/* Receiving compressed DATA while SETTINGS_COMPRESS_DATA == 1 is
|
|
||||||
allowed */
|
|
||||||
|
|
||||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
|
||||||
|
|
||||||
session->local_settings[NGHTTP2_SETTINGS_COMPRESS_DATA] = 1;
|
|
||||||
|
|
||||||
stream = nghttp2_session_open_stream(session, 1,
|
|
||||||
NGHTTP2_STREAM_FLAG_NONE,
|
|
||||||
&pri_spec_default,
|
|
||||||
NGHTTP2_STREAM_OPENED, NULL);
|
|
||||||
|
|
||||||
ud.data_chunk_recv_cb_called = 0;
|
|
||||||
ud.frame_recv_cb_called = 0;
|
|
||||||
rv = nghttp2_session_mem_recv(session, data, 8+4096);
|
|
||||||
CU_ASSERT(8+4096 == rv);
|
|
||||||
|
|
||||||
CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
|
|
||||||
CU_ASSERT(1 == ud.frame_recv_cb_called);
|
|
||||||
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
|
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_nghttp2_session_recv_continuation(void)
|
void test_nghttp2_session_recv_continuation(void)
|
||||||
|
@ -2699,14 +2629,12 @@ void test_nghttp2_submit_data(void)
|
||||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||||
callbacks.send_callback = block_count_send_callback;
|
callbacks.send_callback = block_count_send_callback;
|
||||||
|
|
||||||
data_prd.read_callback = compressed_fixed_length_data_source_read_callback;
|
data_prd.read_callback = fixed_length_data_source_read_callback;
|
||||||
ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
|
ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 2;
|
||||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
||||||
aob = &session->aob;
|
aob = &session->aob;
|
||||||
framebufs = &aob->framebufs;
|
framebufs = &aob->framebufs;
|
||||||
|
|
||||||
session->remote_settings[NGHTTP2_SETTINGS_COMPRESS_DATA] = 1;
|
|
||||||
|
|
||||||
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
|
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
|
||||||
&pri_spec_default, NGHTTP2_STREAM_OPENING,
|
&pri_spec_default, NGHTTP2_STREAM_OPENING,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -2714,8 +2642,6 @@ void test_nghttp2_submit_data(void)
|
||||||
NGHTTP2_FLAG_END_STREAM |
|
NGHTTP2_FLAG_END_STREAM |
|
||||||
NGHTTP2_FLAG_END_SEGMENT, 1, &data_prd));
|
NGHTTP2_FLAG_END_SEGMENT, 1, &data_prd));
|
||||||
|
|
||||||
/* First, no compression */
|
|
||||||
ud.compress_data = 0;
|
|
||||||
ud.block_count = 0;
|
ud.block_count = 0;
|
||||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
||||||
|
@ -2728,21 +2654,6 @@ void test_nghttp2_submit_data(void)
|
||||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT) ==
|
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT) ==
|
||||||
data_frame->hd.flags);
|
data_frame->hd.flags);
|
||||||
|
|
||||||
/* Now compression enabled */
|
|
||||||
ud.compress_data = 1;
|
|
||||||
ud.block_count = 1;
|
|
||||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
|
||||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
|
||||||
nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
|
|
||||||
|
|
||||||
/* This is the last frame, so we must have following flags */
|
|
||||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT |
|
|
||||||
NGHTTP2_FLAG_COMPRESSED) == hd.flags);
|
|
||||||
/* frame->hd.flags has these flags */
|
|
||||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT |
|
|
||||||
NGHTTP2_FLAG_COMPRESSED) ==
|
|
||||||
data_frame->hd.flags);
|
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue