Reworked no automatic WINDOW_UPDATE feature. We added new API
nghttp2_session_consume() which tells the library how many bytes are
consumed by the application. Instead of submitting WINDOW_UPDATE by
the application, the library is now responsible to submit
WINDOW_UPDATE based on consumed bytes. This is more reliable method,
since it enables us to properly send WINDOW_UPDATE for stream and
connection individually. The previous implementation of nghttpx had
broken connection window management.
Now concatenating header values with 0x00 as delimiter is not
necessary because HPACK reference set is removed and the order of
header field fed into HPACK encoder is preserved when they are
decoded.
This change rewrites logging system of nghttpx. Previously access log
and error log are written to stderr or syslog and there was no option
to change stderr to something else. With this change, file path of
access log and error log can be configured separately and logging to
regular file is now added. To support rotating log, if SIGUSR1 signal
is received by nghttpx, it closes the current log files and reopen it
with the same name. The format of access log is changed and has same
look of apache's. But not all columns are not supported yet.
For now, if request has request body, we'll issue RST_STREAM to inform
the peer to stop sending body. RST_STREAM may be sent before error
page header or data, so peer may receive RST_STREAM only.
Previously we do not specify the number of requests each client has to
issue. The each client corresponds to 1 TCP connection. If
connection was not accepted by server or not TLS handshake is not
done, we effectively don't use that connection and the requests
supposed to be issued for those connections are done via other
established connections. If this occurs, servers which do not accept
all connections may gain good benchmark results since they don't have
to pay extra cost to handle all connections (e.g., SSL/TLS handshake).
This change explicitly set the number of requests each client has to
issue so that servers cannot *cheat*.
It looks like setting read-rate and read-burst to 0 makes busy loop.
It seems a bug. On the other hand, we most likely want per-thread
rate limit rather than per-connection. So we decided to drop them.
It seems that if readcb is not set before SSL/TLS handshake, the
incoming data already available when eventcb (BEV_EVENT_CONNECTED
event) is fired is not further notified after setting new readcb. We
knew this fact and call upstream->on_read() in eventcb, but it is
wrong for HTTP/2. We have to call upstream_http2_connhd_readcb to
check connection preface. Otherwise, we consume it by nghttp2 session
and it is treated as unknown frame and connection preface is not
detected properly.
Libevent Openssl filter is very inconvenient in various respect. The
most annoying thing is it somehow emits data when SSL_shutdown is
called. The reason we introduced this filter solution is drop
connection if TLS renegotiation is detected. This commit implements
renegotiation detection and drop connection without filtering.
Cipher suites are chosen by DHE and ECDHE ciphers + GCM (AEAD). Now
default cipher list is the one recommended by Mozilla web site. The
--honor-cipher-order option is removed and now it is always assumed.
ALTSVC and BLOCKED frames are now extension frames. To add new
extension frame without modifying nghttp2_frame union, which causes so
name bump, we separated extension frames from core frames.
nghttp2_frame includes generic nghttp2_extension. The payload member
of nghttp2_extension will point to the structure of extension frame
payload. The frame types of extension frames are defined in
nghttp2_ext_frame_type.
Previously, we use evbuffer_pullup(buf, -1) to linearize the memory
region and it may cause buffer copy. To avoid this, we use the return
value of evbuffer_get_contiguous_space() as 2nd parameter. According
to the libevent manual, by doing so evbuffer_pullup() will not copy or
modify any data in evbuffer.
It seems that specifyig '*' to node parameter in getaddrinfo() is
treated as specifying NULL, but it is not documented. So rather than
relying on this feature, we explicitly treat '*' as "wildcard" address
and specify NULL to node parameter in getaddrinfo().
Now '*,3000' is a default value of --frontend option. Specyfing '*'
binds all addresses including both IPv4 and IPv6.
It appears that some Android client does not like Connection: close in
200 CONNECT response. Browsers fine with this header field. It is
better to remove it. Squid does not emit it too.
Previously stream ID was assigned just before HEADERS or PUSH_PROMISE
was serialized and nghttp2_submit_{request, headers, push_promise} did
not return stream ID. The application has to check assigned stream ID
using before_frame_send_callback. Now it is apparent that priority is
meant to DATA transfer only. Also application can reorder the
requests if it wants. Therefore we can assign stream ID in
nghttp2_submit_* functions and return stream ID from them. With this
change, now application does not have to check stream ID using
before_frame_send_callback and its code will be simplified.
We inherited gzip compression API from spdylay codebase. In spdylay,
the cost of having such API is almost free because spdylay requires
zlib for header compression. nghttp2 no longer uses gzip to header
compression. zlib dependency exists just for gzip compression API,
which is not an essential. So we decided to move gzip code to under
src and remove zlib dependency from libnghttp2 itself. As nghttp2
package, we depend on zlib to compile tools under src.
Currently, nghttpd server only compresses files whose extensions are
one of .html, .js, .css and .txt. nghttp advertises its support of
per-frame compression in SETTINGS frame. To implement this feature,
we added 2 public API: nghttp2_session_get_remote_settings() and
nghttp2_gzip_inflate_finished().
Callback function invoked to adjust priority value for request
HEADERS.
Since the application doesn’t know stream ID when it submits
requests, it may not be able to add correct priority value to HEADERS
frame and forced to use follwing PRIORITY frame. The purpose of this
callback is give the chance to the application to adjust priority
value with the latest information it has just before transmission so
that correct priority is included in HEADERS frame and it doesn’t
have to send additional PRIORITY frame.
The library interface supports compressed DATA. The library does not
deflate nor inflate data payload. When sending data, an application
has to compress data and set NGHTTP2_DATA_FLAG_COMPRESSED to
data_flags parameter in nghttp2_data_source_read_callback. On
receiving, flags parameter in nghttp2_on_data_chunk_recv_callback
includes NGHTTP2_FLAG_COMPRESSED. An application should check the
flags and inflate data as necessary. Since compression context is per
frame, when DATA is seen in nghttp2_on_frame_recv_callback, an
application should reset compression context.
Previously h2load supports SPDY only for https URI. This is because
SPDY has no mechanism to negotiate its protocol version without NPN.
With this change, user can specify the exact protocol version to use
when http URI (without SSL/TLS) is used.
To make adding new option easier, we decided to make the details of
option struct private and hide it from public API. We provide
functions to set individual option value.
If SPDY or HTTP/2 ustream is used and HTTP/2 downstream is used, only
call {spdylay,nghttp2}_resume_data when complete DATA frame was read
in backend to avoid to transmit too small DATA frame to the upstream.
NGHTTP2_CLIENT_CONNECTION_PREFACE has the same content with
NGHTTP2_CLIENT_CONNECTION_HEADER, which is now obsoleted by
NGHTTP2_CLIENT_CONNECTION_PREFACE.
Supplying multiple URIs can simulate more real life situation on
server side. For example, we can supply URIs of html, css and js and
benchmark the server. The -m option is updated so that it defaults to
the number of supplied URIs.
The existing options --{read,write}-{rate,burst} are per connection.
The new options --worker-{read,write}-{rate,burst} are per worker
thread, which is overall rate limit of all connections worker handles.
The profiler and benchmarking showed that calling evbuffer_add()
repeatedly is very costly. To avoid this, we buffer up small writes
into one large chunk and call evbuffer_add() less times.
This function behaves like nghttp2_session_send(), but it does not
use nghttp2_send_callback to send data. Instead, it returns the
serialized data to trasmit and its length to the caller.
* Use 1 Huffman code table for both request and response
* Remove complicated deflater side table size management
* Add encoding context update
* Fix memory leak in inflater
Now previous padding options are removed and instead we added
select_padding_callback to select padding length for each frame
by application. If this callback is not implemented by application,
no padding is added.
This change also fixes the broken session_detect_idle_stream()
if stream_id is our side.
Previously, there is inconsistency when on_frame_recv_callback
is called between HEADERS/PUSH_PROMISE and the other frames.
For former case, it is called before header block, in latter
case, it is called after whole frame is received. To make it
consistent, we call on_frame_recv_callback for HEADERS/PUSH_PROMISE
after its frame is fully received. Since on_frame_recv_callback
can signal the end of header block, we replaced on_end_headers_callback
with on_begin_headers_callback, which is called when the reception
of the header block is started.
Since all headers are not always longer available on one
nghttp2_session_mem_recv call, received headers may be interleaved
with transmission log of the other frames. To make it clear that
each header belongs to which stream, each header is printed with
stream_id.
nghttp2_data is added to nghttp2_frame union. When DATA is
received, nghttp2_on_frame_recv_callback is called. When DATA is
sent, nghttp2_on_frame_send_callback is called.
This stream inflater can inflate incoming header block in streaming
fashion. Currently, we buffer up single name/value pair, but we chose
far more smaller buffer size than HTTP/2 frame size.
evdns_base uses /etc/resolve.conf for *nix like systems,
but all platforms don't have the file (e.g., android device).
For such platforms, address resolution fails.
To fix this problem we use getaddrinfo() directly.