mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 02:58:53 +08:00
Compare commits
255 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
553d741f03 | ||
|
|
6bd728b3c2 | ||
|
|
a99085891a | ||
|
|
68d3724fad | ||
|
|
fe39ec8697 | ||
|
|
c896118747 | ||
|
|
b89140c311 | ||
|
|
a869c39a2c | ||
|
|
0b27f005e0 | ||
|
|
92a20c76e6 | ||
|
|
42ccea806c | ||
|
|
805f36d134 | ||
|
|
e2c0a3e43b | ||
|
|
3572e7c634 | ||
|
|
0479f833fc | ||
|
|
252aeb43e1 | ||
|
|
24fe24b37d | ||
|
|
32603d7eff | ||
|
|
53bfc70c9e | ||
|
|
c4068cd404 | ||
|
|
0aa17f64c1 | ||
|
|
38cfc5c47c | ||
|
|
91c8f085ef | ||
|
|
5da49989f8 | ||
|
|
260131966d | ||
|
|
6862f66c23 | ||
|
|
2f2a7ace81 | ||
|
|
132719f752 | ||
|
|
64b1aae567 | ||
|
|
a8625e15f0 | ||
|
|
e63d6e490a | ||
|
|
7f60de0c51 | ||
|
|
3a46a2c0a4 | ||
|
|
fbff101165 | ||
|
|
526d2c727d | ||
|
|
6c232da679 | ||
|
|
1241c951d6 | ||
|
|
73e79130d1 | ||
|
|
1a1902350b | ||
|
|
eec65826cf | ||
|
|
fc17c0a618 | ||
|
|
2620992003 | ||
|
|
5a2069b55c | ||
|
|
14adcb2d81 | ||
|
|
13660edef2 | ||
|
|
98034286ac | ||
|
|
2a37a28d72 | ||
|
|
7bb154f768 | ||
|
|
eb96aa261f | ||
|
|
232d359cbb | ||
|
|
2d5d9d5d04 | ||
|
|
7ecca39025 | ||
|
|
bc0190c19f | ||
|
|
9a162b81f0 | ||
|
|
a67a8fabff | ||
|
|
989d381aab | ||
|
|
1d65d82cb5 | ||
|
|
4be4d875f3 | ||
|
|
1ab707713f | ||
|
|
cc46d363c5 | ||
|
|
fa082cbdd0 | ||
|
|
016d40ea0f | ||
|
|
fe6d065bb4 | ||
|
|
b4e8bea4b5 | ||
|
|
555d5abac9 | ||
|
|
3137dc4a70 | ||
|
|
4bba4bf66c | ||
|
|
7b3a33a313 | ||
|
|
ee52290de7 | ||
|
|
8f0899a190 | ||
|
|
f6cfd082c7 | ||
|
|
9d81be4b35 | ||
|
|
a62778d6b0 | ||
|
|
ea612a2dce | ||
|
|
026521b097 | ||
|
|
9dc5259593 | ||
|
|
ea8a566d98 | ||
|
|
8c6f9e899f | ||
|
|
552f675466 | ||
|
|
f9a50333d2 | ||
|
|
de4735092a | ||
|
|
1c4df1832b | ||
|
|
1ad1fe6005 | ||
|
|
f05a4830c5 | ||
|
|
9e1b068a4b | ||
|
|
54bff91762 | ||
|
|
63630690a8 | ||
|
|
dbc613e0d0 | ||
|
|
ee354ee6c8 | ||
|
|
df707df21b | ||
|
|
2436acbd23 | ||
|
|
b41835f19b | ||
|
|
42b2430fe1 | ||
|
|
c8f67788e0 | ||
|
|
bbdff112a3 | ||
|
|
02468b1ca1 | ||
|
|
c41f413978 | ||
|
|
e38dd37667 | ||
|
|
f2cf2b625c | ||
|
|
eb05777d88 | ||
|
|
db4a68454a | ||
|
|
6b0b8ea7d5 | ||
|
|
c925c32233 | ||
|
|
514558afc0 | ||
|
|
b9f602b9a2 | ||
|
|
1a99bcc860 | ||
|
|
6b8aa36c98 | ||
|
|
86ddda5c0e | ||
|
|
58b7f4a096 | ||
|
|
4069aab4f7 | ||
|
|
5595ba643e | ||
|
|
77c556901c | ||
|
|
4928959213 | ||
|
|
a200bb1084 | ||
|
|
92a1ca5917 | ||
|
|
97648d257f | ||
|
|
5937b4b6f7 | ||
|
|
787d40129b | ||
|
|
91ad7e150e | ||
|
|
28bde2cef0 | ||
|
|
a9b54a1bfa | ||
|
|
80f0e99f00 | ||
|
|
102ea7c0bb | ||
|
|
85671a69bf | ||
|
|
a3fa257473 | ||
|
|
c4e994c97d | ||
|
|
0b41e20d54 | ||
|
|
cfabce6e70 | ||
|
|
b948c5457d | ||
|
|
3bdf78e8af | ||
|
|
436595df98 | ||
|
|
d3561a63b1 | ||
|
|
1a12a9b397 | ||
|
|
57644e0256 | ||
|
|
7323d4c639 | ||
|
|
e23225689f | ||
|
|
e6ad2eb14f | ||
|
|
d4a22edeb3 | ||
|
|
8f4e2d941f | ||
|
|
1a8da6caec | ||
|
|
dc335b9025 | ||
|
|
93afbc7d2f | ||
|
|
82e2c5bd22 | ||
|
|
53bcafb39f | ||
|
|
59f8397659 | ||
|
|
061732adf0 | ||
|
|
5c2ca28706 | ||
|
|
a8ea86cfe5 | ||
|
|
7451a73def | ||
|
|
889e705f35 | ||
|
|
14d4979c54 | ||
|
|
095bc178f3 | ||
|
|
308738025c | ||
|
|
97366bf55c | ||
|
|
87cadca3d8 | ||
|
|
9803f92e9c | ||
|
|
cbfa021095 | ||
|
|
03746884a4 | ||
|
|
6ed710adbd | ||
|
|
44b4cda200 | ||
|
|
69a4f3bf42 | ||
|
|
5334cb5acc | ||
|
|
6ca24264e4 | ||
|
|
37a631278f | ||
|
|
5c42687759 | ||
|
|
b636e9744f | ||
|
|
b873930802 | ||
|
|
bc53c81616 | ||
|
|
09c485e712 | ||
|
|
d247470da2 | ||
|
|
90bfea77e0 | ||
|
|
cf0576253f | ||
|
|
4aca2f0b59 | ||
|
|
9d711f65f7 | ||
|
|
0eab08a7cf | ||
|
|
b9c4757d21 | ||
|
|
1fcd881395 | ||
|
|
cd0564ddfa | ||
|
|
dd435b51ab | ||
|
|
ff60cc6b71 | ||
|
|
80743ddc7b | ||
|
|
36a8f24559 | ||
|
|
b25e19e876 | ||
|
|
e9660c3558 | ||
|
|
8c3b379b66 | ||
|
|
b2bb6f1db1 | ||
|
|
59e3783f3f | ||
|
|
d56ecd7414 | ||
|
|
ef4e39be55 | ||
|
|
d42f31ca78 | ||
|
|
084e4487ed | ||
|
|
24897aa50d | ||
|
|
3e50ef439d | ||
|
|
87602e5d72 | ||
|
|
d0c27d5229 | ||
|
|
ebf214c8fc | ||
|
|
250ea53e4b | ||
|
|
01af6ea70c | ||
|
|
7522d50d1a | ||
|
|
cc03a12b75 | ||
|
|
9eff511c5e | ||
|
|
a96ac6f0a0 | ||
|
|
213a63d97d | ||
|
|
8d4548b9c1 | ||
|
|
44f2e6ae1d | ||
|
|
0cd7d268f3 | ||
|
|
f3a9041851 | ||
|
|
776a8c64f6 | ||
|
|
524a1f9498 | ||
|
|
28cfae162a | ||
|
|
b0123448a4 | ||
|
|
2d15dca096 | ||
|
|
5f05135d1b | ||
|
|
3b6b4ff066 | ||
|
|
0c8ec7bfa6 | ||
|
|
2c05b8d6f0 | ||
|
|
45c4187d8f | ||
|
|
87029e05af | ||
|
|
363914c3f7 | ||
|
|
1316065c14 | ||
|
|
2b6a181bef | ||
|
|
bf68df9ef4 | ||
|
|
e7f6089b0e | ||
|
|
a1500b0ee3 | ||
|
|
14001052f8 | ||
|
|
95ab54c79d | ||
|
|
5e84f767f0 | ||
|
|
c47855085b | ||
|
|
1442b1bd0a | ||
|
|
763293a050 | ||
|
|
cc94632b29 | ||
|
|
5df770b9c1 | ||
|
|
4bc9afe20a | ||
|
|
522faeb24f | ||
|
|
362ff09183 | ||
|
|
ccea4d42b5 | ||
|
|
ebbe065716 | ||
|
|
3a97f21383 | ||
|
|
12ced1cddc | ||
|
|
3576f20e5a | ||
|
|
7ae6e6b4c5 | ||
|
|
a2486daee1 | ||
|
|
8bf440b89c | ||
|
|
e9cdb9c896 | ||
|
|
c4804ee50b | ||
|
|
95cb284e27 | ||
|
|
c4ccc376df | ||
|
|
6133110386 | ||
|
|
6f58434d89 | ||
|
|
3fd5d0af79 | ||
|
|
1a6855ea7d | ||
|
|
0312521ac9 | ||
|
|
67b0e0c2d6 | ||
|
|
966e3a1308 | ||
|
|
fd8f8e2708 |
50
.gitignore
vendored
50
.gitignore
vendored
@@ -1,14 +1,18 @@
|
||||
# emacs backup file
|
||||
*~
|
||||
*.o
|
||||
*.lo
|
||||
|
||||
# autotools
|
||||
*.la
|
||||
depcomp
|
||||
*.lo
|
||||
*.m4
|
||||
*.o
|
||||
.deps/
|
||||
.libs/
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
libtool
|
||||
missing
|
||||
autom4te.cache/
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
@@ -16,36 +20,14 @@ config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
.deps/
|
||||
.libs
|
||||
lib/includes/nghttp2/nghttp2ver.h
|
||||
lib/libnghttp2.pc
|
||||
src/libnghttp2_asio.pc
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
stamp-h1
|
||||
.deps/
|
||||
INSTALL
|
||||
.DS_STORE
|
||||
compile
|
||||
test-driver
|
||||
.dirstamp
|
||||
doc/index.rst
|
||||
doc/nghttp2.h.rst
|
||||
doc/nghttp2ver.h.rst
|
||||
doc/package_README.rst
|
||||
doc/tutorial-client.rst
|
||||
doc/tutorial-server.rst
|
||||
doc/nghttpx-howto.rst
|
||||
doc/h2load-howto.rst
|
||||
doc/tutorial-hpack.rst
|
||||
doc/python-apiref.rst
|
||||
doc/building-android-binary.rst
|
||||
doc/asio_http2.h.rst
|
||||
doc/asio_http2_server.h.rst
|
||||
doc/asio_http2_client.h.rst
|
||||
doc/libnghttp2_asio.rst
|
||||
doc/contribute.rst
|
||||
python/setup.py
|
||||
python/dist
|
||||
python/MANIFEST
|
||||
|
||||
# test logs generated by `make check`
|
||||
*.log
|
||||
*.trs
|
||||
|
||||
46
.travis.yml
46
.travis.yml
@@ -1,31 +1,31 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
#Disable gcc build for the moment...
|
||||
# - gcc
|
||||
- gcc
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
- libstdc++-4.9-dev
|
||||
- autoconf
|
||||
- automake
|
||||
- autotools-dev
|
||||
- libtool
|
||||
- pkg-config
|
||||
- zlib1g-dev
|
||||
- libcunit1-dev
|
||||
- libssl-dev
|
||||
- libxml2-dev
|
||||
- libev-dev
|
||||
- libevent-dev
|
||||
- libjansson-dev
|
||||
- libjemalloc-dev
|
||||
before_install:
|
||||
- $CC --version
|
||||
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
|
||||
- sudo apt-get update -qq
|
||||
#Install and use gcc-4.8 (don't build with gcc-4.6)
|
||||
#libstdc++-4.8 is needed by Clang to build too
|
||||
- sudo apt-get -qq install g++-4.8 libstdc++-4.8-dev
|
||||
- >
|
||||
sudo apt-get install --no-install-recommends -qq
|
||||
autoconf
|
||||
automake
|
||||
autotools-dev
|
||||
libtool
|
||||
pkg-config
|
||||
zlib1g-dev
|
||||
libcunit1-dev
|
||||
libssl-dev
|
||||
libxml2-dev
|
||||
libev-dev
|
||||
libevent-dev
|
||||
libjansson-dev
|
||||
libjemalloc-dev
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
- $CC --version
|
||||
before_script:
|
||||
- autoreconf -i
|
||||
|
||||
18
CONTRIBUTION
Normal file
18
CONTRIBUTION
Normal file
@@ -0,0 +1,18 @@
|
||||
[The text below was composed based on 1.2. License section of
|
||||
curl/libcurl project.]
|
||||
|
||||
When contributing with code, you agree to put your changes and new
|
||||
code under the same license nghttp2 is already using unless stated and
|
||||
agreed otherwise.
|
||||
|
||||
When changing existing source code, you do not alter the copyright of
|
||||
the original file(s). The copyright will still be owned by the
|
||||
original creator(s) or those who have been assigned copyright by the
|
||||
original author(s).
|
||||
|
||||
By submitting a patch to the nghttp2 project, you are assumed to have
|
||||
the right to the code and to be allowed by your employer or whatever
|
||||
to hand over that patch/code to us. We will credit you for your
|
||||
changes as far as possible, to give credit but also to keep a trace
|
||||
back to who made what changes. Please always provide us with your
|
||||
full real name when contributing!
|
||||
19
COPYING
19
COPYING
@@ -20,22 +20,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
[The text below was composed based on 1.2. License section of
|
||||
curl/libcurl project.]
|
||||
|
||||
When contributing with code, you agree to put your changes and new
|
||||
code under the same license nghttp2 is already using unless stated and
|
||||
agreed otherwise.
|
||||
|
||||
When changing existing source code, you do not alter the copyright of
|
||||
the original file(s). The copyright will still be owned by the
|
||||
original creator(s) or those who have been assigned copyright by the
|
||||
original author(s).
|
||||
|
||||
By submitting a patch to the nghttp2 project, you are assumed to have
|
||||
the right to the code and to be allowed by your employer or whatever
|
||||
to hand over that patch/code to us. We will credit you for your
|
||||
changes as far as possible, to give credit but also to keep a trace
|
||||
back to who made what changes. Please always provide us with your
|
||||
full real name when contributing!
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# vim: ft=dockerfile:
|
||||
# Dockerfile to build nghttp2 android binary
|
||||
#
|
||||
# $ sudo docker build -t nghttp2-android - < Dockerfile.android
|
||||
@@ -9,7 +10,7 @@
|
||||
#
|
||||
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
|
||||
|
||||
FROM ubuntu
|
||||
FROM ubuntu:trusty
|
||||
|
||||
MAINTAINER Tatsuhiro Tsujikawa
|
||||
|
||||
@@ -29,9 +30,10 @@ RUN apt-get install -y make binutils autoconf automake autotools-dev libtool \
|
||||
genisoimage libc6-i386 lib32stdc++6
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin
|
||||
RUN chmod a+x android-ndk-r10c-linux-x86_64.bin
|
||||
RUN ./android-ndk-r10c-linux-x86_64.bin
|
||||
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin && \
|
||||
chmod a+x android-ndk-r10c-linux-x86_64.bin && \
|
||||
./android-ndk-r10c-linux-x86_64.bin && \
|
||||
rm android-ndk-r10c-linux-x86_64.bin
|
||||
|
||||
WORKDIR /root/build/android-ndk-r10c
|
||||
RUN /bin/bash build/tools/make-standalone-toolchain.sh \
|
||||
@@ -57,20 +59,24 @@ RUN autoreconf -i && \
|
||||
make install
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.1j.tar.gz
|
||||
RUN tar xf openssl-1.0.1j.tar.gz
|
||||
WORKDIR /root/build/openssl-1.0.1j
|
||||
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.2a.tar.gz && \
|
||||
tar xf openssl-1.0.2a.tar.gz && \
|
||||
rm openssl-1.0.2a.tar.gz
|
||||
|
||||
WORKDIR /root/build/openssl-1.0.2a
|
||||
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
|
||||
./Configure --prefix=$PREFIX android && \
|
||||
make && make install_sw
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz
|
||||
RUN curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch
|
||||
RUN tar xf libev-4.19.tar.gz
|
||||
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz && \
|
||||
curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch && \
|
||||
tar xf libev-4.19.tar.gz && \
|
||||
rm libev-4.19.tar.gz
|
||||
|
||||
WORKDIR /root/build/libev-4.19
|
||||
RUN patch -p1 < ../libev-4.19-android.patch
|
||||
RUN ./configure \
|
||||
RUN patch -p1 < ../libev-4.19-android.patch && \
|
||||
./configure \
|
||||
--host=arm-linux-androideabi \
|
||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||
--prefix=$PREFIX \
|
||||
@@ -95,9 +101,9 @@ RUN autoreconf -i && \
|
||||
--disable-threads \
|
||||
LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \
|
||||
LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \
|
||||
CPPFLAGS="-I$PREFIX/include" \
|
||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||
CXXFLAGS="-fno-strict-aliasing" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-L$PREFIX/lib" && \
|
||||
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
|
||||
make && \
|
||||
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp
|
||||
|
||||
574
README.rst
574
README.rst
@@ -13,26 +13,18 @@ An HPACK encoder and decoder are available as a public API.
|
||||
|
||||
An experimental high level C++ library is also available.
|
||||
|
||||
We have Python bindings of this libary, but we do not have full
|
||||
We have Python bindings of this library, but we do not have full
|
||||
code coverage yet.
|
||||
|
||||
Development Status
|
||||
------------------
|
||||
|
||||
We started to implement h2-14
|
||||
(http://tools.ietf.org/html/draft-ietf-httpbis-http2-14), and header
|
||||
compression
|
||||
(http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09).
|
||||
We have implemented `RFC 7540 <https://tools.ietf.org/html/rfc7540>`_
|
||||
HTTP/2 and `RFC 7541 <https://tools.ietf.org/html/rfc7541>`_ HPACK -
|
||||
Header Compression for HTTP/2
|
||||
|
||||
The nghttp2 code base was forked from the spdylay project.
|
||||
|
||||
=========================== =======
|
||||
HTTP/2 Features Support
|
||||
=========================== =======
|
||||
Core frames handling Yes
|
||||
Dependency Tree Yes
|
||||
Large header (CONTINUATION) Yes
|
||||
=========================== =======
|
||||
The nghttp2 code base was forked from the spdylay
|
||||
(https://github.com/tatsuhiro-t/spdylay) project.
|
||||
|
||||
Public Test Server
|
||||
------------------
|
||||
@@ -46,9 +38,9 @@ implementation.
|
||||
and ``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
|
||||
connection.
|
||||
|
||||
* http://nghttp2.org/ (Upgrade / Direct)
|
||||
* http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct)
|
||||
|
||||
``h2c-14`` and ``http/1.1``.
|
||||
``h2c`` and ``http/1.1``.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
@@ -79,7 +71,7 @@ ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
|
||||
To enable the SPDY protocol in the application program ``nghttpx`` and
|
||||
``h2load``, the following package is required:
|
||||
|
||||
* spdylay >= 1.3.0
|
||||
* spdylay >= 1.3.2
|
||||
|
||||
To enable ``-a`` option (getting linked assets from the downloaded
|
||||
resource) in ``nghttp``, the following package is required:
|
||||
@@ -139,6 +131,33 @@ To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
|
||||
them from crashing. A patch is welcome to make multi threading work
|
||||
on Mac OS X platform.
|
||||
|
||||
Notes for building on Windows (Mingw/Cygwin)
|
||||
--------------------------------------------
|
||||
|
||||
Under Mingw environment, you can only compile the library, it's
|
||||
``libnghttp2-X.dll`` and ``libnghttp2.a``.
|
||||
|
||||
If you want to compile the applications(``h2load``, ``nghttp``,
|
||||
``nghttpx``, ``nghttpd``), you need to use the Cygwin environment.
|
||||
|
||||
Under Cygwin environment, to compile the applications you need to
|
||||
compile and install the libev first.
|
||||
|
||||
Secondly, you need to undefine the macro ``__STRICT_ANSI__``, if you
|
||||
not, the functions ``fdopen``, ``fileno`` and ``strptime`` will not
|
||||
available.
|
||||
|
||||
the sample command like this::
|
||||
|
||||
$ export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
|
||||
$ export CXXFLAGS=$CFLAGS
|
||||
$ ./configure
|
||||
$ make
|
||||
|
||||
If you want to compile the applications under ``examples/``, you need
|
||||
to remove or rename the ``event.h`` from libev's installation, because
|
||||
it conflicts with libevent's installation.
|
||||
|
||||
Building the documentation
|
||||
--------------------------
|
||||
|
||||
@@ -160,7 +179,7 @@ https://nghttp2.org/documentation/
|
||||
Unit tests
|
||||
----------
|
||||
|
||||
Unit tests are done by simply running `make check`.
|
||||
Unit tests are done by simply running ``make check``.
|
||||
|
||||
Integration tests
|
||||
-----------------
|
||||
@@ -185,6 +204,104 @@ To run the tests, run the following command under
|
||||
|
||||
Inside the tests, we use port 3009 to run the test subject server.
|
||||
|
||||
Migration from v0.7.15 or earlier
|
||||
---------------------------------
|
||||
|
||||
nghttp2 v1.0.0 introduced several backward incompatible changes. In
|
||||
this section, we describe these changes and how to migrate to v1.0.0.
|
||||
|
||||
ALPN protocol ID is now ``h2`` and ``h2c``
|
||||
++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Previously we announced ``h2-14`` and ``h2c-14``. v1.0.0 implements
|
||||
final protocol version, and we changed ALPN ID to ``h2`` and ``h2c``.
|
||||
The macros ``NGHTTP2_PROTO_VERSION_ID``,
|
||||
``NGHTTP2_PROTO_VERSION_ID_LEN``,
|
||||
``NGHTTP2_CLEARTEXT_PROTO_VERSION_ID``, and
|
||||
``NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN`` have been updated to
|
||||
reflect this change.
|
||||
|
||||
Basically, existing applications do not have to do anything, just
|
||||
recompiling is enough for this change.
|
||||
|
||||
Use word "client magic" where we use "client connection preface"
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
We use "client connection preface" to mean first 24 bytes of client
|
||||
connection preface. This is technically not correct, since client
|
||||
connection preface is composed of 24 bytes client magic byte string
|
||||
followed by SETTINGS frame. For clarification, we call "client magic"
|
||||
for this 24 bytes byte string and updated API.
|
||||
|
||||
* ``NGHTTP2_CLIENT_CONNECTION_PREFACE`` was replaced with
|
||||
``NGHTTP2_CLIENT_MAGIC``.
|
||||
* ``NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN`` was replaced with
|
||||
``NGHTTP2_CLIENT_MAGIC_LEN``.
|
||||
* ``NGHTTP2_BAD_PREFACE`` was renamed as ``NGHTTP2_BAD_CLIENT_MAGIC``
|
||||
|
||||
The alreay deprecated ``NGHTTP2_CLIENT_CONNECTION_HEADER`` and
|
||||
``NGHTTP2_CLIENT_CONNECTION_HEADER_LEN`` were removed.
|
||||
|
||||
If application uses these macros, just replace old ones with new ones.
|
||||
Since v1.0.0, client magic is sent by library (see next subsection),
|
||||
so client application may just remove these macro use.
|
||||
|
||||
Client magic is sent by library
|
||||
+++++++++++++++++++++++++++++++
|
||||
|
||||
Previously nghttp2 library did not send client magic, which is first
|
||||
24 bytes byte string of client connection preface, and client
|
||||
applications have to send it by themselves. Since v1.0.0, client
|
||||
magic is sent by library via first call of ``nghttp2_session_send()``
|
||||
or ``nghttp2_session_mem_send()``.
|
||||
|
||||
The client applications which send client magic must remove the
|
||||
relevant code.
|
||||
|
||||
Remove HTTP Alternative Services (Alt-Svc) related code
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Alt-Svc specification is not finalized yet. To make our API stable,
|
||||
we have decided to remove all Alt-Svc related API from nghttp2.
|
||||
|
||||
* ``NGHTTP2_EXT_ALTSVC`` was removed.
|
||||
* ``nghttp2_ext_altsvc`` was removed.
|
||||
|
||||
We have already removed the functionality of Alt-Svc in v0.7 series
|
||||
and they have been essentially noop. The application using these
|
||||
macro and struct, remove those lines.
|
||||
|
||||
Use nghttp2_error in nghttp2_on_invalid_frame_recv_callback
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Previously ``nghttp2_on_invalid_frame_recv_cb_called`` took the
|
||||
``error_code``, defined in ``nghttp2_error_code``, as parameter. But
|
||||
they are not detailed enough to debug. Therefore, we decided to use
|
||||
more detailed ``nghttp2_error`` values instead.
|
||||
|
||||
The application using this callback should update the callback
|
||||
signature. If it treats ``error_code`` as HTTP/2 error code, update
|
||||
the code so that it is treated as ``nghttp2_error``.
|
||||
|
||||
Receive client magic by default
|
||||
+++++++++++++++++++++++++++++++
|
||||
|
||||
Previously nghttp2 did not process client magic (24 bytes byte
|
||||
string). To make it deal with it, we had to use
|
||||
``nghttp2_option_set_recv_client_preface()``. Since v1.0.0, nghttp2
|
||||
processes client magic by default and
|
||||
``nghttp2_option_set_recv_client_preface()`` was removed.
|
||||
|
||||
Some application may want to disable this behaviour, so we added
|
||||
``nghttp2_option_set_no_recv_client_magic()`` to achieve this.
|
||||
|
||||
The application using ``nghttp2_option_set_recv_client_preface()``
|
||||
with nonzero value, just remove it.
|
||||
|
||||
The application using ``nghttp2_option_set_recv_client_preface()``
|
||||
with zero value or not using it must use
|
||||
``nghttp2_option_set_no_recv_client_magic()`` with nonzero value.
|
||||
|
||||
Client, Server and Proxy programs
|
||||
---------------------------------
|
||||
|
||||
@@ -200,140 +317,180 @@ It has verbose output mode for framing information. Here is sample
|
||||
output from ``nghttp`` client::
|
||||
|
||||
$ nghttp -nv https://nghttp2.org
|
||||
[ 0.033][NPN] server offers:
|
||||
* h2-14
|
||||
* spdy/3.1
|
||||
* http/1.1
|
||||
The negotiated protocol: h2-14
|
||||
[ 0.068] send SETTINGS frame <length=15, flags=0x00, stream_id=0>
|
||||
(niv=3)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
||||
[SETTINGS_COMPRESS_DATA(5):1]
|
||||
[ 0.068] send HEADERS frame <length=46, flags=0x05, stream_id=1>
|
||||
; END_STREAM | END_HEADERS
|
||||
(padlen=0)
|
||||
[ 0.067] Connected
|
||||
The negotiated protocol: h2
|
||||
[ 0.135] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
|
||||
(niv=2)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
|
||||
[ 0.135] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
|
||||
(dep_stream_id=0, weight=201, exclusive=0)
|
||||
[ 0.135] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
|
||||
(dep_stream_id=0, weight=101, exclusive=0)
|
||||
[ 0.135] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
|
||||
(dep_stream_id=0, weight=1, exclusive=0)
|
||||
[ 0.135] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
|
||||
(dep_stream_id=7, weight=1, exclusive=0)
|
||||
[ 0.135] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
|
||||
(dep_stream_id=3, weight=1, exclusive=0)
|
||||
[ 0.135] send HEADERS frame <length=39, flags=0x25, stream_id=13>
|
||||
; END_STREAM | END_HEADERS | PRIORITY
|
||||
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
|
||||
; Open new stream
|
||||
:authority: nghttp2.org
|
||||
:method: GET
|
||||
:path: /
|
||||
:scheme: https
|
||||
:authority: nghttp2.org
|
||||
accept: */*
|
||||
accept-encoding: gzip, deflate
|
||||
user-agent: nghttp2/0.4.0-DEV
|
||||
[ 0.068] recv SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
||||
user-agent: nghttp2/1.0.0-DEV
|
||||
[ 0.135] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
|
||||
(niv=2)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
||||
[ 0.068] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
|
||||
[ 0.135] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[ 0.079] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
[ 0.165] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[ 0.080] (stream_id=1, noind=0) :status: 200
|
||||
[ 0.080] (stream_id=1, noind=0) accept-ranges: bytes
|
||||
[ 0.080] (stream_id=1, noind=0) age: 15
|
||||
[ 0.080] (stream_id=1, noind=0) content-length: 40243
|
||||
[ 0.080] (stream_id=1, noind=0) content-type: text/html
|
||||
[ 0.080] (stream_id=1, noind=0) date: Wed, 14 May 2014 15:14:30 GMT
|
||||
[ 0.080] (stream_id=1, noind=0) etag: "535d0eea-9d33"
|
||||
[ 0.080] (stream_id=1, noind=0) last-modified: Sun, 27 Apr 2014 14:06:34 GMT
|
||||
[ 0.080] (stream_id=1, noind=0) server: nginx/1.4.6 (Ubuntu)
|
||||
[ 0.080] (stream_id=1, noind=0) x-varnish: 2114900538 2114900537
|
||||
[ 0.080] (stream_id=1, noind=0) via: 1.1 varnish, 1.1 nghttpx
|
||||
[ 0.080] (stream_id=1, noind=0) strict-transport-security: max-age=31536000
|
||||
[ 0.080] recv HEADERS frame <length=162, flags=0x04, stream_id=1>
|
||||
[ 0.166] recv (stream_id=13) :status: 200
|
||||
[ 0.166] recv (stream_id=13) date: Fri, 15 May 2015 14:45:22 GMT
|
||||
[ 0.166] recv (stream_id=13) content-type: text/html
|
||||
[ 0.166] recv (stream_id=13) last-modified: Fri, 15 May 2015 14:20:46 GMT
|
||||
[ 0.166] recv (stream_id=13) etag: W/"555600be-1a7f"
|
||||
[ 0.166] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
|
||||
[ 0.166] recv (stream_id=13) content-encoding: gzip
|
||||
[ 0.166] recv (stream_id=13) server: nghttpx nghttp2/1.0.0-DEV
|
||||
[ 0.166] recv (stream_id=13) via: 1.1 nghttpx
|
||||
[ 0.166] recv (stream_id=13) strict-transport-security: max-age=31536000
|
||||
[ 0.166] recv HEADERS frame <length=166, flags=0x04, stream_id=13>
|
||||
; END_HEADERS
|
||||
(padlen=0)
|
||||
; First response header
|
||||
[ 0.080] recv DATA frame <length=3786, flags=0x00, stream_id=1>
|
||||
[ 0.080] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.081] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.093] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.093] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.094] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.094] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.094] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.096] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.096] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
||||
(window_size_increment=36554)
|
||||
[ 0.096] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=1>
|
||||
(window_size_increment=36554)
|
||||
[ 0.108] recv DATA frame <length=3689, flags=0x00, stream_id=1>
|
||||
[ 0.108] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
||||
[ 0.166] recv (stream_id=13) :method: GET
|
||||
[ 0.166] recv (stream_id=13) :scheme: https
|
||||
[ 0.166] recv (stream_id=13) :path: /stylesheets/screen.css
|
||||
[ 0.166] recv (stream_id=13) :authority: nghttp2.org
|
||||
[ 0.166] recv (stream_id=13) accept-encoding: gzip, deflate
|
||||
[ 0.166] recv (stream_id=13) user-agent: nghttp2/1.0.0-DEV
|
||||
[ 0.166] recv PUSH_PROMISE frame <length=50, flags=0x04, stream_id=13>
|
||||
; END_HEADERS
|
||||
(padlen=0, promised_stream_id=2)
|
||||
[ 0.166] recv DATA frame <length=2670, flags=0x01, stream_id=13>
|
||||
; END_STREAM
|
||||
[ 0.108] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
||||
[ 0.167] recv (stream_id=2) :status: 200
|
||||
[ 0.167] recv (stream_id=2) date: Fri, 15 May 2015 14:45:22 GMT
|
||||
[ 0.167] recv (stream_id=2) content-type: text/css
|
||||
[ 0.167] recv (stream_id=2) last-modified: Fri, 15 May 2015 14:20:46 GMT
|
||||
[ 0.167] recv (stream_id=2) etag: W/"555600be-9845"
|
||||
[ 0.167] recv (stream_id=2) content-encoding: gzip
|
||||
[ 0.167] recv (stream_id=2) server: nghttpx nghttp2/1.0.0-DEV
|
||||
[ 0.167] recv (stream_id=2) via: 1.1 nghttpx
|
||||
[ 0.167] recv (stream_id=2) strict-transport-security: max-age=31536000
|
||||
[ 0.167] recv HEADERS frame <length=32, flags=0x04, stream_id=2>
|
||||
; END_HEADERS
|
||||
(padlen=0)
|
||||
; First push response header
|
||||
[ 0.196] recv DATA frame <length=8715, flags=0x01, stream_id=2>
|
||||
; END_STREAM
|
||||
[ 0.196] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
|
||||
|
||||
The HTTP Upgrade is performed like this::
|
||||
The HTTP Upgrade is performed like so::
|
||||
|
||||
$ nghttp -nvu http://nghttp2.org
|
||||
[ 0.013] HTTP Upgrade request
|
||||
[ 0.137] Connected
|
||||
[ 0.137] HTTP Upgrade request
|
||||
GET / HTTP/1.1
|
||||
Host: nghttp2.org
|
||||
Connection: Upgrade, HTTP2-Settings
|
||||
Upgrade: h2c-14
|
||||
HTTP2-Settings: AwAAAGQEAAD__wUAAAAB
|
||||
Upgrade: h2c
|
||||
HTTP2-Settings: AAMAAABkAAQAAP__
|
||||
Accept: */*
|
||||
User-Agent: nghttp2/0.4.0-DEV
|
||||
User-Agent: nghttp2/1.0.0-DEV
|
||||
|
||||
|
||||
[ 0.024] HTTP Upgrade response
|
||||
[ 0.156] HTTP Upgrade response
|
||||
HTTP/1.1 101 Switching Protocols
|
||||
Connection: Upgrade
|
||||
Upgrade: h2c-14
|
||||
Upgrade: h2c
|
||||
|
||||
|
||||
[ 0.024] HTTP Upgrade success
|
||||
[ 0.024] send SETTINGS frame <length=15, flags=0x00, stream_id=0>
|
||||
(niv=3)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
||||
[SETTINGS_COMPRESS_DATA(5):1]
|
||||
[ 0.024] recv SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
||||
[ 0.156] HTTP Upgrade success
|
||||
[ 0.157] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
|
||||
(niv=2)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
||||
[ 0.024] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[ 0.024] (stream_id=1, noind=0) :status: 200
|
||||
[ 0.024] (stream_id=1, noind=0) accept-ranges: bytes
|
||||
[ 0.024] (stream_id=1, noind=0) age: 10
|
||||
[ 0.024] (stream_id=1, noind=0) content-length: 40243
|
||||
[ 0.024] (stream_id=1, noind=0) content-type: text/html
|
||||
[ 0.024] (stream_id=1, noind=0) date: Wed, 14 May 2014 15:16:34 GMT
|
||||
[ 0.024] (stream_id=1, noind=0) etag: "535d0eea-9d33"
|
||||
[ 0.024] (stream_id=1, noind=0) last-modified: Sun, 27 Apr 2014 14:06:34 GMT
|
||||
[ 0.024] (stream_id=1, noind=0) server: nginx/1.4.6 (Ubuntu)
|
||||
[ 0.024] (stream_id=1, noind=0) x-varnish: 2114900541 2114900540
|
||||
[ 0.024] (stream_id=1, noind=0) via: 1.1 varnish, 1.1 nghttpx
|
||||
[ 0.024] recv HEADERS frame <length=148, flags=0x04, stream_id=1>
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
|
||||
[ 0.157] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
|
||||
(dep_stream_id=0, weight=201, exclusive=0)
|
||||
[ 0.157] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
|
||||
(dep_stream_id=0, weight=101, exclusive=0)
|
||||
[ 0.157] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
|
||||
(dep_stream_id=0, weight=1, exclusive=0)
|
||||
[ 0.157] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
|
||||
(dep_stream_id=7, weight=1, exclusive=0)
|
||||
[ 0.157] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
|
||||
(dep_stream_id=3, weight=1, exclusive=0)
|
||||
[ 0.157] send PRIORITY frame <length=5, flags=0x00, stream_id=1>
|
||||
(dep_stream_id=11, weight=16, exclusive=0)
|
||||
[ 0.157] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
|
||||
(niv=2)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
|
||||
[ 0.157] recv (stream_id=1) :status: 200
|
||||
[ 0.157] recv (stream_id=1) date: Fri, 15 May 2015 14:46:08 GMT
|
||||
[ 0.157] recv (stream_id=1) content-type: text/html
|
||||
[ 0.157] recv (stream_id=1) content-length: 6783
|
||||
[ 0.157] recv (stream_id=1) last-modified: Fri, 15 May 2015 14:20:46 GMT
|
||||
[ 0.157] recv (stream_id=1) etag: "555600be-1a7f"
|
||||
[ 0.157] recv (stream_id=1) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
|
||||
[ 0.157] recv (stream_id=1) accept-ranges: bytes
|
||||
[ 0.157] recv (stream_id=1) server: nghttpx nghttp2/1.0.0-DEV
|
||||
[ 0.157] recv (stream_id=1) via: 1.1 nghttpx
|
||||
[ 0.157] recv HEADERS frame <length=157, flags=0x04, stream_id=1>
|
||||
; END_HEADERS
|
||||
(padlen=0)
|
||||
; First response header
|
||||
[ 0.024] recv DATA frame <length=3786, flags=0x00, stream_id=1>
|
||||
[ 0.025] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.031] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.031] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.032] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.032] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.033] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.033] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.033] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
||||
(window_size_increment=33164)
|
||||
[ 0.033] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=1>
|
||||
(window_size_increment=33164)
|
||||
[ 0.038] recv DATA frame <length=4096, flags=0x00, stream_id=1>
|
||||
[ 0.038] recv DATA frame <length=3689, flags=0x00, stream_id=1>
|
||||
[ 0.038] recv DATA frame <length=0, flags=0x01, stream_id=1>
|
||||
; END_STREAM
|
||||
[ 0.038] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
[ 0.157] recv (stream_id=1) :method: GET
|
||||
[ 0.157] recv (stream_id=1) :scheme: http
|
||||
[ 0.157] recv (stream_id=1) :path: /stylesheets/screen.css
|
||||
[ 0.157] recv (stream_id=1) host: nghttp2.org
|
||||
[ 0.157] recv (stream_id=1) user-agent: nghttp2/1.0.0-DEV
|
||||
[ 0.157] recv PUSH_PROMISE frame <length=49, flags=0x04, stream_id=1>
|
||||
; END_HEADERS
|
||||
(padlen=0, promised_stream_id=2)
|
||||
[ 0.157] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[ 0.038] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
||||
[ 0.161] recv DATA frame <length=6783, flags=0x01, stream_id=1>
|
||||
; END_STREAM
|
||||
[ 0.162] recv (stream_id=2) :status: 200
|
||||
[ 0.162] recv (stream_id=2) date: Fri, 15 May 2015 14:46:08 GMT
|
||||
[ 0.162] recv (stream_id=2) content-type: text/css
|
||||
[ 0.162] recv (stream_id=2) content-length: 38981
|
||||
[ 0.162] recv (stream_id=2) last-modified: Fri, 15 May 2015 14:20:46 GMT
|
||||
[ 0.162] recv (stream_id=2) etag: "555600be-9845"
|
||||
[ 0.162] recv (stream_id=2) accept-ranges: bytes
|
||||
[ 0.162] recv (stream_id=2) server: nghttpx nghttp2/1.0.0-DEV
|
||||
[ 0.162] recv (stream_id=2) via: 1.1 nghttpx
|
||||
[ 0.162] recv HEADERS frame <length=36, flags=0x04, stream_id=2>
|
||||
; END_HEADERS
|
||||
(padlen=0)
|
||||
; First push response header
|
||||
[ 0.191] recv DATA frame <length=16384, flags=0x00, stream_id=2>
|
||||
[ 0.215] recv DATA frame <length=7952, flags=0x00, stream_id=2>
|
||||
[ 0.215] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
|
||||
(window_size_increment=33322)
|
||||
[ 0.238] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=2>
|
||||
(window_size_increment=33549)
|
||||
[ 0.238] recv DATA frame <length=14645, flags=0x01, stream_id=2>
|
||||
; END_STREAM
|
||||
[ 0.238] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[ 0.238] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
|
||||
|
||||
Using the ``-s`` option, ``nghttp`` prints out some timing information for
|
||||
requests, sorted by completion time::
|
||||
@@ -342,24 +499,26 @@ requests, sorted by completion time::
|
||||
***** Statistics *****
|
||||
|
||||
Request timing:
|
||||
complete: relative time from protocol handshake to stream close
|
||||
request: relative time from protocol handshake to request
|
||||
transmission. If '*' is shown, this was pushed by server.
|
||||
process: time for request and response
|
||||
code: HTTP status code
|
||||
size: number of bytes received as response body without
|
||||
inflation.
|
||||
URI: request URI
|
||||
responseEnd: the time when last byte of response was received
|
||||
relative to connectEnd
|
||||
requestStart: the time just before first byte of request was sent
|
||||
relative to connectEnd. If '*' is shown, this was
|
||||
pushed by server.
|
||||
process: responseEnd - requestStart
|
||||
code: HTTP status code
|
||||
size: number of bytes received as response body without
|
||||
inflation.
|
||||
URI: request URI
|
||||
|
||||
see http://www.w3.org/TR/resource-timing/#processing-model
|
||||
|
||||
sorted by 'complete'
|
||||
|
||||
complete request process code size request path
|
||||
+11.07ms +120us 10.95ms 200 9K /
|
||||
+16.77ms * +8.80ms 7.98ms 200 8K /stylesheets/screen.css
|
||||
+27.00ms +11.16ms 15.84ms 200 3K /javascripts/octopress.js
|
||||
+27.40ms +11.16ms 16.24ms 200 3K /javascripts/modernizr-2.0.js
|
||||
+76.14ms +11.17ms 64.97ms 200 171K /images/posts/with-pri-blog.png
|
||||
+88.52ms +11.17ms 77.36ms 200 174K /images/posts/without-pri-blog.png
|
||||
id responseEnd requestStart process code size request path
|
||||
13 +37.19ms +280us 36.91ms 200 2K /
|
||||
2 +72.65ms * +36.38ms 36.26ms 200 8K /stylesheets/screen.css
|
||||
17 +77.43ms +38.67ms 38.75ms 200 3K /javascripts/octopress.js
|
||||
15 +78.12ms +38.66ms 39.46ms 200 3K /javascripts/modernizr-2.0.js
|
||||
|
||||
Using the ``-r`` option, ``nghttp`` writes more detailed timing data to
|
||||
the given file in HAR format.
|
||||
@@ -381,59 +540,73 @@ Just like ``nghttp``, it has a verbose output mode for framing
|
||||
information. Here is sample output from ``nghttpd``::
|
||||
|
||||
$ nghttpd --no-tls -v 8080
|
||||
IPv4: listen on port 8080
|
||||
IPv6: listen on port 8080
|
||||
[id=1] [ 15.921] send SETTINGS frame <length=10, flags=0x00, stream_id=0>
|
||||
IPv4: listen 0.0.0.0:8080
|
||||
IPv6: listen :::8080
|
||||
[id=1] [ 1.521] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
|
||||
(niv=1)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
|
||||
[id=1] [ 1.521] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
|
||||
(niv=2)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
||||
[SETTINGS_COMPRESS_DATA(5):1]
|
||||
[id=1] [ 15.921] recv SETTINGS frame <length=15, flags=0x00, stream_id=0>
|
||||
(niv=3)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(3):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(4):65535]
|
||||
[SETTINGS_COMPRESS_DATA(5):1]
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) :authority: localhost:8080
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) :method: GET
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) :path: /
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) :scheme: http
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) accept: */*
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) accept-encoding: gzip, deflate
|
||||
[id=1] [ 15.921] (stream_id=1, noind=0) user-agent: nghttp2/0.4.0-DEV
|
||||
[id=1] [ 15.921] recv HEADERS frame <length=48, flags=0x05, stream_id=1>
|
||||
; END_STREAM | END_HEADERS
|
||||
(padlen=0)
|
||||
[SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
|
||||
[SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
|
||||
[id=1] [ 1.521] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=3>
|
||||
(dep_stream_id=0, weight=201, exclusive=0)
|
||||
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=5>
|
||||
(dep_stream_id=0, weight=101, exclusive=0)
|
||||
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=7>
|
||||
(dep_stream_id=0, weight=1, exclusive=0)
|
||||
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=9>
|
||||
(dep_stream_id=7, weight=1, exclusive=0)
|
||||
[id=1] [ 1.521] recv PRIORITY frame <length=5, flags=0x00, stream_id=11>
|
||||
(dep_stream_id=3, weight=1, exclusive=0)
|
||||
[id=1] [ 1.521] recv (stream_id=13) :method: GET
|
||||
[id=1] [ 1.521] recv (stream_id=13) :path: /
|
||||
[id=1] [ 1.521] recv (stream_id=13) :scheme: http
|
||||
[id=1] [ 1.521] recv (stream_id=13) :authority: localhost:8080
|
||||
[id=1] [ 1.521] recv (stream_id=13) accept: */*
|
||||
[id=1] [ 1.521] recv (stream_id=13) accept-encoding: gzip, deflate
|
||||
[id=1] [ 1.521] recv (stream_id=13) user-agent: nghttp2/1.0.0-DEV
|
||||
[id=1] [ 1.521] recv HEADERS frame <length=41, flags=0x25, stream_id=13>
|
||||
; END_STREAM | END_HEADERS | PRIORITY
|
||||
(padlen=0, dep_stream_id=11, weight=16, exclusive=0)
|
||||
; Open new stream
|
||||
[id=1] [ 15.921] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
[id=1] [ 1.521] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[id=1] [ 15.921] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
|
||||
; ACK
|
||||
(niv=0)
|
||||
[id=1] [ 15.921] send HEADERS frame <length=82, flags=0x04, stream_id=1>
|
||||
[id=1] [ 1.521] send HEADERS frame <length=86, flags=0x04, stream_id=13>
|
||||
; END_HEADERS
|
||||
(padlen=0)
|
||||
; First response header
|
||||
:status: 200
|
||||
server: nghttpd nghttp2/1.0.0-DEV
|
||||
content-length: 10
|
||||
cache-control: max-age=3600
|
||||
content-length: 612
|
||||
date: Wed, 14 May 2014 15:19:03 GMT
|
||||
last-modified: Sat, 08 Mar 2014 16:04:06 GMT
|
||||
server: nghttpd nghttp2/0.4.0-DEV
|
||||
[id=1] [ 15.922] send DATA frame <length=381, flags=0x20, stream_id=1>
|
||||
; COMPRESSED
|
||||
[id=1] [ 15.922] send DATA frame <length=0, flags=0x01, stream_id=1>
|
||||
date: Fri, 15 May 2015 14:49:04 GMT
|
||||
last-modified: Tue, 30 Sep 2014 12:40:52 GMT
|
||||
[id=1] [ 1.522] send DATA frame <length=10, flags=0x01, stream_id=13>
|
||||
; END_STREAM
|
||||
[id=1] [ 15.922] stream_id=1 closed
|
||||
[id=1] [ 15.922] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=0, error_code=NO_ERROR(0), opaque_data(0)=[])
|
||||
[id=1] [ 15.922] closed
|
||||
[id=1] [ 1.522] stream_id=13 closed
|
||||
[id=1] [ 1.522] recv GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
|
||||
[id=1] [ 1.522] closed
|
||||
|
||||
nghttpx - proxy
|
||||
+++++++++++++++
|
||||
|
||||
``nghttpx`` is a multi-threaded reverse proxy for ``h2-14``, SPDY and
|
||||
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server push.
|
||||
It has several operational modes:
|
||||
``nghttpx`` is a multi-threaded reverse proxy for HTTP/2, SPDY and
|
||||
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server
|
||||
push.
|
||||
|
||||
``nghttpx`` implements `important performance-oriented features
|
||||
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
||||
session IDs, session tickets (with automatic key rotation), OCSP
|
||||
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and SPDY &
|
||||
HTTP/2.
|
||||
|
||||
``nghttpx`` has several operational modes:
|
||||
|
||||
================== ============================ ============== =============
|
||||
Mode option Frontend Backend Note
|
||||
@@ -446,8 +619,8 @@ default mode HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 Reverse proxy
|
||||
================== ============================ ============== =============
|
||||
|
||||
The interesting mode at the moment is the default mode. It works like
|
||||
a reverse proxy and listens for ``h2-14``, SPDY and HTTP/1.1 and can
|
||||
be deployed as a SSL/TLS terminator for existing web server.
|
||||
a reverse proxy and listens for HTTP/2, SPDY and HTTP/1.1 and can be
|
||||
deployed as a SSL/TLS terminator for existing web server.
|
||||
|
||||
The default mode, ``--http2-proxy`` and ``--http2-bridge`` modes use
|
||||
SSL/TLS in the frontend connection by default. To disable SSL/TLS,
|
||||
@@ -456,7 +629,7 @@ disabled in the frontend and incoming HTTP/1.1 connections can be
|
||||
upgraded to HTTP/2 through HTTP Upgrade.
|
||||
|
||||
The ``--http2-bridge``, ``--client`` and ``--client-proxy`` modes use
|
||||
SSL/TLS in the backend connection by deafult. To disable SSL/TLS, use
|
||||
SSL/TLS in the backend connection by default. To disable SSL/TLS, use
|
||||
the ``--backend-no-tls`` option.
|
||||
|
||||
``nghttpx`` supports a configuration file. See the ``--conf`` option and
|
||||
@@ -548,6 +721,7 @@ follows::
|
||||
spawning thread #0: 100 concurrent clients, 100000 total requests
|
||||
Protocol: TLSv1.2
|
||||
Cipher: ECDHE-RSA-AES128-GCM-SHA256
|
||||
Server Temp Key: ECDH P-256 256 bits
|
||||
progress: 10% done
|
||||
progress: 20% done
|
||||
progress: 30% done
|
||||
@@ -559,12 +733,14 @@ follows::
|
||||
progress: 90% done
|
||||
progress: 100% done
|
||||
|
||||
finished in 7.10s, 14092 req/s, 55.67MB/s
|
||||
finished in 771.26ms, 129658 req/s, 4.71MB/s
|
||||
requests: 100000 total, 100000 started, 100000 done, 100000 succeeded, 0 failed, 0 errored
|
||||
status codes: 100000 2xx, 0 3xx, 0 4xx, 0 5xx
|
||||
traffic: 414200800 bytes total, 2723100 bytes headers, 409600000 bytes data
|
||||
traffic: 3812300 bytes total, 1009900 bytes headers, 1000000 bytes data
|
||||
min max mean sd +/- sd
|
||||
time for request: 283.86ms 1.46s 659.70ms 150.87ms 84.68%
|
||||
time for request: 25.12ms 124.55ms 51.07ms 15.36ms 84.87%
|
||||
time for connect: 208.94ms 254.67ms 241.38ms 7.95ms 63.00%
|
||||
time to 1st byte: 209.11ms 254.80ms 241.51ms 7.94ms 63.00%
|
||||
|
||||
The above example issued total 100,000 requests, using 100 concurrent
|
||||
clients (in other words, 100 HTTP/2 sessions), and a maximum of 100 streams
|
||||
@@ -751,7 +927,7 @@ max_deflate_size
|
||||
The maximum header table size the encoder uses. This can be smaller
|
||||
than ``max_size``. In this case, the encoder only uses up to first
|
||||
``max_deflate_size`` buffer. Since the header table size is still
|
||||
``max_size``, the encoder has to keep track of entries ouside the
|
||||
``max_size``, the encoder has to keep track of entries outside the
|
||||
``max_deflate_size`` but inside the ``max_size`` and make sure
|
||||
that they are no longer referenced.
|
||||
|
||||
@@ -1074,32 +1250,32 @@ Here is sample code to use the client API:
|
||||
session sess(io_service, "localhost", "3000");
|
||||
|
||||
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
|
||||
boost::system::error_code ec;
|
||||
boost::system::error_code ec;
|
||||
|
||||
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
|
||||
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
|
||||
|
||||
req->on_response([](const response &res) {
|
||||
// print status code and response header fields.
|
||||
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
|
||||
for (auto &kv : res.header()) {
|
||||
std::cerr << kv.first << ": " << kv.second.value << "\n";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
req->on_response([](const response &res) {
|
||||
// print status code and response header fields.
|
||||
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
|
||||
for (auto &kv : res.header()) {
|
||||
std::cerr << kv.first << ": " << kv.second.value << "\n";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
res.on_data([](const uint8_t *data, std::size_t len) {
|
||||
std::cerr.write(reinterpret_cast<const char *>(data), len);
|
||||
std::cerr << std::endl;
|
||||
});
|
||||
});
|
||||
res.on_data([](const uint8_t *data, std::size_t len) {
|
||||
std::cerr.write(reinterpret_cast<const char *>(data), len);
|
||||
std::cerr << std::endl;
|
||||
});
|
||||
});
|
||||
|
||||
req->on_close([&sess](uint32_t error_code) {
|
||||
// shutdown session after first request was done.
|
||||
sess.shutdown();
|
||||
});
|
||||
req->on_close([&sess](uint32_t error_code) {
|
||||
// shutdown session after first request was done.
|
||||
sess.shutdown();
|
||||
});
|
||||
});
|
||||
|
||||
sess.on_error([](const boost::system::error_code &ec) {
|
||||
std::cerr << "error: " << ec.message() << std::endl;
|
||||
std::cerr << "error: " << ec.message() << std::endl;
|
||||
});
|
||||
|
||||
io_service.run();
|
||||
@@ -1239,7 +1415,7 @@ original creator(s) or those who have been assigned copyright by the
|
||||
original author(s).
|
||||
|
||||
By submitting a patch to the nghttp2 project, you (or your employer, as
|
||||
the case may be) agree to assign the copyright of your submission to us.
|
||||
the case may be) agree to assign the copyright of your submission to us.
|
||||
.. the above really needs to be reworded to pass legal muster.
|
||||
We will credit you for your
|
||||
changes as far as possible, to give credit but also to keep a trace
|
||||
|
||||
@@ -42,6 +42,6 @@ PATH=$TOOLCHAIN/bin:$PATH
|
||||
--enable-werror \
|
||||
CC=clang \
|
||||
CXX=clang++ \
|
||||
CPPFLAGS="-I$PREFIX/include" \
|
||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-L$PREFIX/lib"
|
||||
LDFLAGS="-fPIE -pie -L$PREFIX/lib"
|
||||
|
||||
107
configure.ac
107
configure.ac
@@ -25,29 +25,16 @@ dnl Do not change user variables!
|
||||
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [0.7.9], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.0.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
LT_PREREQ([2.2.6])
|
||||
LT_INIT()
|
||||
dnl See versioning rule:
|
||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 12)
|
||||
AC_SUBST(LT_REVISION, 2)
|
||||
AC_SUBST(LT_AGE, 7)
|
||||
|
||||
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
||||
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
|
||||
patch=`echo $PACKAGE_VERSION |cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g"`
|
||||
|
||||
PACKAGE_VERSION_NUM=`printf "0x%02x%02x%02x" "$major" "$minor" "$patch"`
|
||||
|
||||
AC_SUBST(PACKAGE_VERSION_NUM)
|
||||
|
||||
AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
# comment out for now since this requires automake 1.13 or higher and
|
||||
# travis has older one.
|
||||
@@ -55,8 +42,23 @@ AM_INIT_AUTOMAKE([subdir-objects])
|
||||
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
dnl See versioning rule:
|
||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 14)
|
||||
AC_SUBST(LT_REVISION, 0)
|
||||
AC_SUBST(LT_AGE, 0)
|
||||
|
||||
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
||||
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
|
||||
patch=`echo $PACKAGE_VERSION |cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g"`
|
||||
|
||||
PACKAGE_VERSION_NUM=`printf "0x%02x%02x%02x" "$major" "$minor" "$patch"`
|
||||
|
||||
AC_SUBST(PACKAGE_VERSION_NUM)
|
||||
|
||||
dnl Checks for command-line options
|
||||
AC_ARG_ENABLE([werror],
|
||||
[AS_HELP_STRING([--enable-werror],
|
||||
@@ -129,10 +131,12 @@ AC_ARG_VAR([CYTHON], [the Cython executable])
|
||||
dnl Checks for programs
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
|
||||
if [test "x$request_python_bindings" != "xno"]; then
|
||||
@@ -358,9 +362,23 @@ if test "x${request_jemalloc}" != "xno"; then
|
||||
AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
|
||||
[$PTHREAD_LDFLAGS])
|
||||
LIBS=$LIBS_OLD
|
||||
|
||||
if test "x${have_jemalloc}" = "xyes"; then
|
||||
jemalloc_libs=${ac_cv_search_malloc_stats_print}
|
||||
else
|
||||
# On Darwin, malloc_stats_print is je_malloc_stats_print
|
||||
AC_SEARCH_LIBS([je_malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
|
||||
[$PTHREAD_LDFLAGS])
|
||||
LIBS=$LIBS_OLD
|
||||
|
||||
if test "x${have_jemalloc}" = "xyes"; then
|
||||
jemalloc_libs=${ac_cv_search_je_malloc_stats_print}
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${have_jemalloc}" = "xyes" &&
|
||||
test "x${ac_cv_search_malloc_stats_print}" != "xnone required"; then
|
||||
JEMALLOC_LIBS=${ac_cv_search_malloc_stats_print}
|
||||
test "x${jemalloc_libs}" != "xnone required"; then
|
||||
JEMALLOC_LIBS=${jemalloc_libs}
|
||||
AC_SUBST([JEMALLOC_LIBS])
|
||||
fi
|
||||
fi
|
||||
@@ -498,23 +516,23 @@ AM_CONDITIONAL([ENABLE_FAILMALLOC], [ test "x${enable_failmalloc}" = "xyes" ])
|
||||
AC_HEADER_ASSERT
|
||||
AC_CHECK_HEADERS([ \
|
||||
arpa/inet.h \
|
||||
fcntl.h \
|
||||
inttypes.h \
|
||||
limits.h \
|
||||
netdb.h \
|
||||
netinet/in.h \
|
||||
pwd.h \
|
||||
stddef.h \
|
||||
stdint.h \
|
||||
stdlib.h \
|
||||
string.h \
|
||||
sys/socket.h \
|
||||
sys/time.h \
|
||||
syslog.h \
|
||||
time.h \
|
||||
unistd.h \
|
||||
])
|
||||
|
||||
case "${host}" in
|
||||
*mingw*)
|
||||
# For ntohl, ntohs in Windows
|
||||
AC_CHECK_HEADERS([winsock2.h])
|
||||
;;
|
||||
esac
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_SSIZE_T
|
||||
@@ -522,8 +540,16 @@ AC_TYPE_UINT8_T
|
||||
AC_TYPE_UINT16_T
|
||||
AC_TYPE_UINT32_T
|
||||
AC_TYPE_UINT64_T
|
||||
AC_TYPE_INT8_T
|
||||
AC_TYPE_INT16_T
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_INT64_T
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_PID_T
|
||||
AC_TYPE_UID_T
|
||||
AC_CHECK_TYPES([ptrdiff_t])
|
||||
AC_C_BIGENDIAN
|
||||
AC_C_INLINE
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [have_struct_tm_tm_gmtoff=yes],
|
||||
@@ -542,12 +568,34 @@ AC_CHECK_SIZEOF([int *])
|
||||
if test "x$cross_compiling" != "xyes"; then
|
||||
AC_FUNC_MALLOC
|
||||
fi
|
||||
|
||||
AC_FUNC_CHOWN
|
||||
AC_FUNC_ERROR_AT_LINE
|
||||
AC_FUNC_FORK
|
||||
# Don't check realloc, since LeakSanitizer detects memory leak during check
|
||||
# AC_FUNC_REALLOC
|
||||
AC_FUNC_STRERROR_R
|
||||
AC_FUNC_STRNLEN
|
||||
|
||||
AC_CHECK_FUNCS([ \
|
||||
_Exit \
|
||||
accept4 \
|
||||
dup2 \
|
||||
getcwd \
|
||||
getpwnam \
|
||||
localtime_r \
|
||||
memchr \
|
||||
memmove \
|
||||
memset \
|
||||
socket \
|
||||
sqrt \
|
||||
strchr \
|
||||
strdup \
|
||||
strerror \
|
||||
strndup \
|
||||
strstr \
|
||||
strtol \
|
||||
strtoul \
|
||||
timegm \
|
||||
])
|
||||
|
||||
@@ -564,13 +612,6 @@ AM_CONDITIONAL([ENABLE_TINY_NGHTTPD],
|
||||
[ test "x${have_epoll}" = "xyes" &&
|
||||
test "x${have_timerfd_create}" = "xyes"])
|
||||
|
||||
dnl Windows library for winsock2
|
||||
case "${host}" in
|
||||
*mingw*)
|
||||
LIBS="$LIBS -lws2_32"
|
||||
;;
|
||||
esac
|
||||
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
CFLAGS=
|
||||
|
||||
|
||||
2
contrib/.gitignore
vendored
2
contrib/.gitignore
vendored
@@ -1 +1,3 @@
|
||||
nghttpx-init
|
||||
nghttpx.service
|
||||
nghttpx-upstart.conf
|
||||
|
||||
@@ -21,19 +21,24 @@
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
EXTRA_DIST = nghttpx-init.in nghttpx-logrotate
|
||||
configfiles = nghttpx-init nghttpx.service nghttpx-upstart.conf
|
||||
|
||||
EXTRA_DIST = $(configfiles:%=%.in) nghttpx-logrotate
|
||||
|
||||
edit = sed -e 's|@bindir[@]|$(bindir)|g'
|
||||
|
||||
nghttpx-init: Makefile
|
||||
nghttpx-init: %: $(srcdir)/%.in
|
||||
rm -f $@ $@.tmp
|
||||
$(edit) $(srcdir)/$@.in > $@.tmp
|
||||
$(edit) $< > $@.tmp
|
||||
chmod +x $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
nghttpx-init: $(srcdir)/nghttpx-init.in
|
||||
nghttpx.service nghttpx-upstart.conf: %: $(srcdir)/%.in
|
||||
$(edit) $< > $@
|
||||
|
||||
all-local: nghttpx-init
|
||||
$(configfiles): Makefile
|
||||
|
||||
all-local: $(configfiles)
|
||||
|
||||
clean-local:
|
||||
-rm -f nghttpx-init nghttpx-init.tmp
|
||||
-rm -f nghttpx-init.tmp $(configfiles)
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
/var/log/nghttpx/*.log {
|
||||
weekly
|
||||
missingok
|
||||
rotate 52
|
||||
compress
|
||||
delaycompress
|
||||
notifempty
|
||||
create 0640 www-data adm
|
||||
sharedscripts
|
||||
prerotate
|
||||
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
|
||||
run-parts /etc/logrotate.d/httpd-prerotate; \
|
||||
fi \
|
||||
endscript
|
||||
postrotate
|
||||
[ -s /run/nghttpx.pid ] && kill -USR1 `cat /run/nghttpx.pid`
|
||||
endscript
|
||||
weekly
|
||||
rotate 52
|
||||
missingok
|
||||
compress
|
||||
delaycompress
|
||||
notifempty
|
||||
postrotate
|
||||
killall -USR1 nghttpx 2> /dev/null || true
|
||||
endscript
|
||||
}
|
||||
|
||||
8
contrib/nghttpx-upstart.conf.in
Normal file
8
contrib/nghttpx-upstart.conf.in
Normal file
@@ -0,0 +1,8 @@
|
||||
# vim: ft=upstart:
|
||||
|
||||
description "HTTP/2 reverse proxy"
|
||||
|
||||
start on runlevel [2]
|
||||
stop on runlevel [016]
|
||||
|
||||
exec @bindir@/nghttpx
|
||||
10
contrib/nghttpx.service.in
Normal file
10
contrib/nghttpx.service.in
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=HTTP/2 experimental proxy
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=@bindir@/nghttpx --errorlog-syslog
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
doc/.gitignore
vendored
23
doc/.gitignore
vendored
@@ -1,3 +1,24 @@
|
||||
# generated files
|
||||
apiref.rst
|
||||
asio_http2.h.rst
|
||||
asio_http2_client.h.rst
|
||||
asio_http2_server.h.rst
|
||||
building-android-binary.rst
|
||||
conf.py
|
||||
manual
|
||||
contribute.rst
|
||||
enums.rst
|
||||
h2load-howto.rst
|
||||
index.rst
|
||||
libnghttp2_asio.rst
|
||||
macros.rst
|
||||
manual/
|
||||
nghttp2.h.rst
|
||||
nghttp2_*.rst
|
||||
nghttp2ver.h.rst
|
||||
nghttpx-howto.rst
|
||||
package_README.rst
|
||||
python-apiref.rst
|
||||
tutorial-client.rst
|
||||
tutorial-hpack.rst
|
||||
tutorial-server.rst
|
||||
types.rst
|
||||
|
||||
126
doc/Makefile.am
126
doc/Makefile.am
@@ -23,10 +23,111 @@
|
||||
|
||||
man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1
|
||||
|
||||
APIDOCS= \
|
||||
apiref.rst \
|
||||
macros.rst \
|
||||
enums.rst \
|
||||
types.rst \
|
||||
nghttp2_check_header_name.rst \
|
||||
nghttp2_check_header_value.rst \
|
||||
nghttp2_hd_deflate_bound.rst \
|
||||
nghttp2_hd_deflate_change_table_size.rst \
|
||||
nghttp2_hd_deflate_del.rst \
|
||||
nghttp2_hd_deflate_hd.rst \
|
||||
nghttp2_hd_deflate_new.rst \
|
||||
nghttp2_hd_deflate_new2.rst \
|
||||
nghttp2_hd_inflate_change_table_size.rst \
|
||||
nghttp2_hd_inflate_del.rst \
|
||||
nghttp2_hd_inflate_end_headers.rst \
|
||||
nghttp2_hd_inflate_hd.rst \
|
||||
nghttp2_hd_inflate_new.rst \
|
||||
nghttp2_hd_inflate_new2.rst \
|
||||
nghttp2_is_fatal.rst \
|
||||
nghttp2_nv_compare_name.rst \
|
||||
nghttp2_option_del.rst \
|
||||
nghttp2_option_new.rst \
|
||||
nghttp2_option_set_no_auto_window_update.rst \
|
||||
nghttp2_option_set_no_http_messaging.rst \
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
||||
nghttp2_option_set_no_recv_client_magic.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
nghttp2_priority_spec_default_init.rst \
|
||||
nghttp2_priority_spec_init.rst \
|
||||
nghttp2_select_next_protocol.rst \
|
||||
nghttp2_session_callbacks_del.rst \
|
||||
nghttp2_session_callbacks_new.rst \
|
||||
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_frame_not_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_header_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
||||
nghttp2_session_callbacks_set_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_send_data_callback.rst \
|
||||
nghttp2_session_client_new.rst \
|
||||
nghttp2_session_client_new2.rst \
|
||||
nghttp2_session_client_new3.rst \
|
||||
nghttp2_session_consume.rst \
|
||||
nghttp2_session_consume_connection.rst \
|
||||
nghttp2_session_consume_stream.rst \
|
||||
nghttp2_session_del.rst \
|
||||
nghttp2_session_get_effective_local_window_size.rst \
|
||||
nghttp2_session_get_effective_recv_data_length.rst \
|
||||
nghttp2_session_get_last_proc_stream_id.rst \
|
||||
nghttp2_session_get_next_stream_id.rst \
|
||||
nghttp2_session_get_outbound_queue_size.rst \
|
||||
nghttp2_session_get_remote_settings.rst \
|
||||
nghttp2_session_get_remote_window_size.rst \
|
||||
nghttp2_session_get_stream_effective_local_window_size.rst \
|
||||
nghttp2_session_get_stream_effective_recv_data_length.rst \
|
||||
nghttp2_session_get_stream_local_close.rst \
|
||||
nghttp2_session_get_stream_remote_close.rst \
|
||||
nghttp2_session_get_stream_remote_window_size.rst \
|
||||
nghttp2_session_get_stream_user_data.rst \
|
||||
nghttp2_session_mem_recv.rst \
|
||||
nghttp2_session_mem_send.rst \
|
||||
nghttp2_session_recv.rst \
|
||||
nghttp2_session_resume_data.rst \
|
||||
nghttp2_session_send.rst \
|
||||
nghttp2_session_server_new.rst \
|
||||
nghttp2_session_server_new2.rst \
|
||||
nghttp2_session_server_new3.rst \
|
||||
nghttp2_session_set_next_stream_id.rst \
|
||||
nghttp2_session_set_stream_user_data.rst \
|
||||
nghttp2_session_terminate_session.rst \
|
||||
nghttp2_session_terminate_session2.rst \
|
||||
nghttp2_session_upgrade.rst \
|
||||
nghttp2_session_want_read.rst \
|
||||
nghttp2_session_want_write.rst \
|
||||
nghttp2_strerror.rst \
|
||||
nghttp2_submit_data.rst \
|
||||
nghttp2_submit_goaway.rst \
|
||||
nghttp2_submit_headers.rst \
|
||||
nghttp2_submit_ping.rst \
|
||||
nghttp2_submit_priority.rst \
|
||||
nghttp2_submit_push_promise.rst \
|
||||
nghttp2_submit_request.rst \
|
||||
nghttp2_submit_response.rst \
|
||||
nghttp2_submit_rst_stream.rst \
|
||||
nghttp2_submit_settings.rst \
|
||||
nghttp2_submit_shutdown_notice.rst \
|
||||
nghttp2_submit_trailer.rst \
|
||||
nghttp2_submit_window_update.rst \
|
||||
nghttp2_version.rst
|
||||
|
||||
EXTRA_DIST = \
|
||||
mkapiref.py \
|
||||
README.rst \
|
||||
apiref-header.rst \
|
||||
programmers-guide.rst \
|
||||
$(APIDOCS) \
|
||||
nghttp.1.rst \
|
||||
nghttpd.1.rst \
|
||||
nghttpx.1.rst \
|
||||
@@ -99,13 +200,30 @@ help:
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
apiref.rst: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
|
||||
apiref.rst macros.rst enums.rst types.rst: \
|
||||
$(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
|
||||
$(top_builddir)/lib/includes/nghttp2/nghttp2.h
|
||||
$(PYTHON) $(top_srcdir)/doc/mkapiref.py \
|
||||
--header $(top_srcdir)/doc/apiref-header.rst $^ > $@
|
||||
$@ macros.rst enums.rst types.rst . $^
|
||||
|
||||
# Inspired by
|
||||
# http://www.gnu.org/savannah-checkouts/gnu/automake/manual/html_node/Multiple-Outputs.html
|
||||
apidoc.stamp: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
|
||||
$(top_builddir)/lib/includes/nghttp2/nghttp2.h
|
||||
@rm -f apidoc.tmp
|
||||
@touch apidoc.tmp
|
||||
$(PYTHON) $(top_srcdir)/doc/mkapiref.py \
|
||||
$@ macros.rst enums.rst types.rst . $^
|
||||
@mv -f apidoc.tmp $@
|
||||
$(APIDOC): apidoc.stamp
|
||||
## Recover from the removal of $@
|
||||
@if test -f $@; then :; else \
|
||||
rm -f apidoc.stamp; \
|
||||
$(MAKE) $(AM_MAKEFLAGS) apidoc.stamp; \
|
||||
fi
|
||||
|
||||
clean-local:
|
||||
-rm apiref.rst
|
||||
-rm $(APIDOCS)
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html-local: apiref.rst
|
||||
|
||||
2
doc/_themes/sphinx_rtd_theme/__init__.py
vendored
2
doc/_themes/sphinx_rtd_theme/__init__.py
vendored
@@ -5,7 +5,7 @@ From https://github.com/ryan-roemer/sphinx-bootstrap-theme.
|
||||
"""
|
||||
import os
|
||||
|
||||
VERSION = (0, 1, 5)
|
||||
VERSION = (0, 1, 8)
|
||||
|
||||
__version__ = ".".join(str(v) for v in VERSION)
|
||||
__version_full__ = __version__
|
||||
|
||||
16
doc/_themes/sphinx_rtd_theme/breadcrumbs.html
vendored
16
doc/_themes/sphinx_rtd_theme/breadcrumbs.html
vendored
@@ -6,12 +6,16 @@
|
||||
{% endfor %}
|
||||
<li>{{ title }}</li>
|
||||
<li class="wy-breadcrumbs-aside">
|
||||
{% if display_github %}
|
||||
<a href="https://github.com/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-github"> Edit on GitHub</a>
|
||||
{% elif display_bitbucket %}
|
||||
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-bitbucket"> Edit on Bitbucket</a>
|
||||
{% elif show_source and has_source and sourcename %}
|
||||
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
|
||||
{% if pagename != "search" %}
|
||||
{% if display_github %}
|
||||
<a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-github"> Edit on GitHub</a>
|
||||
{% elif display_bitbucket %}
|
||||
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-bitbucket"> Edit on Bitbucket</a>
|
||||
{% elif show_source and source_url_prefix %}
|
||||
<a href="{{ source_url_prefix }}{{ pagename }}{{ source_suffix }}">View page source</a>
|
||||
{% elif show_source and has_source and sourcename %}
|
||||
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
9
doc/_themes/sphinx_rtd_theme/footer.html
vendored
9
doc/_themes/sphinx_rtd_theme/footer.html
vendored
@@ -2,10 +2,10 @@
|
||||
{% if next or prev %}
|
||||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||||
{% if next %}
|
||||
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
{% endif %}
|
||||
{% if prev %}
|
||||
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -28,6 +28,9 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{%- if show_sphinx %}
|
||||
{% trans %}Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %}.
|
||||
|
||||
{%- endif %}
|
||||
|
||||
</footer>
|
||||
|
||||
|
||||
27
doc/_themes/sphinx_rtd_theme/layout.html
vendored
27
doc/_themes/sphinx_rtd_theme/layout.html
vendored
@@ -12,6 +12,7 @@
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
{{ metatags }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% block htmltitle %}
|
||||
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
|
||||
@@ -23,7 +24,6 @@
|
||||
{% endif %}
|
||||
|
||||
{# CSS #}
|
||||
<link href='https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic|Roboto+Slab:400,700|Inconsolata:400,700&subset=latin,cyrillic' rel='stylesheet' type='text/css'>
|
||||
|
||||
{# OPENSEARCH #}
|
||||
{% if not embedded %}
|
||||
@@ -42,6 +42,10 @@
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{% endfor %}
|
||||
|
||||
{% for cssfile in extra_css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{% endfor %}
|
||||
|
||||
{%- block linktags %}
|
||||
{%- if hasdoc('about') %}
|
||||
<link rel="author" title="{{ _('About these documents') }}"
|
||||
@@ -71,7 +75,7 @@
|
||||
{%- block extrahead %} {% endblock %}
|
||||
|
||||
{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
|
||||
<script src="_static/js/modernizr.min.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -83,14 +87,27 @@
|
||||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||||
<div class="wy-side-nav-search">
|
||||
{% block sidebartitle %}
|
||||
<a href="{{ pathto(master_doc) }}" class="fa fa-home"> {{ project }}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% if logo and theme_logo_only %}
|
||||
<a href="{{ pathto(master_doc) }}">
|
||||
{% else %}
|
||||
<a href="{{ pathto(master_doc) }}" class="icon icon-home"> {{ project }}
|
||||
{% endif %}
|
||||
|
||||
{% if logo %}
|
||||
{# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #}
|
||||
<img src="{{ pathto('_static/' + logo, 1) }}" class="logo" />
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% include "searchbox.html" %}
|
||||
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
||||
{% block menu %}
|
||||
{% set toctree = toctree(maxdepth=2, collapse=False, includehidden=True) %}
|
||||
{% set toctree = toctree(maxdepth=4, collapse=False, includehidden=True) %}
|
||||
{% if toctree %}
|
||||
{{ toctree }}
|
||||
{% else %}
|
||||
|
||||
7
doc/_themes/sphinx_rtd_theme/static/css/badge_only.css.map
vendored
Normal file
7
doc/_themes/sphinx_rtd_theme/static/css/badge_only.css.map
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"mappings": "CAyDA,SAAY,EACV,qBAAsB,EAAE,UAAW,EAqDrC,QAAS,EARP,IAAK,EAAE,AAAC,EACR,+BAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,cAAO,EACL,IAAK,EAAE,GAAI,EC1Gb,SAkBC,EAjBC,UAAW,ECFJ,UAAW,EDGlB,UAAW,EAHqC,KAAM,EAItD,SAAU,EAJsD,KAAM,EAapE,EAAG,EAAE,qCAAwB,EAC7B,EAAG,EAAE,0PAAyE,ECZpF,SAAU,EACR,MAAO,EAAE,WAAY,EACrB,UAAW,EAAE,UAAW,EACxB,SAAU,EAAE,KAAM,EAClB,UAAW,EAAE,KAAM,EACnB,UAAW,EAAE,AAAC,EACd,cAAe,EAAE,MAAO,EAG1B,IAAK,EACH,MAAO,EAAE,WAAY,EACrB,cAAe,EAAE,MAAO,EAIxB,KAAG,EACD,MAAO,EAAE,WAAY,EACvB,sCAAiB,EAGf,IAAK,EAAE,MAAY,EAEvB,KAAM,EACJ,cAAe,EAAE,GAAI,EACrB,UAAW,EAAE,EAAG,EAChB,UAAW,EAAE,KAAM,EAEjB,YAAG,EACD,IAAK,EAAE,IAAI,EACb,oDAAiB,EAGf,aAAc,EAAE,OAAQ,EAG9B,cAAe,EACb,MAAO,EAAE,EAAO,EAElB,gBAAiB,EACf,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,kBAAmB,EACjB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,qBAAsB,EACpB,MAAO,EAAE,EAAO,EAElB,uBAAwB,EACtB,MAAO,EAAE,EAAO,ECnElB,YAAa,EACX,OAAQ,EAAE,IAAK,EACf,KAAM,EAAE,AAAC,EACT,GAAI,EAAE,AAAC,EACP,IAAK,EC6E+B,IAAK,ED5EzC,IAAK,ECE+B,MAAyB,EDD7D,SAAU,EAAE,MAAkC,EAC9C,SAAU,EAAE,iBAAiC,EAC7C,UAAW,EEAyB,sDAAM,EFC1C,MAAO,EC+E6B,EAAG,ED9EvC,cAAC,EACC,IAAK,ECqE6B,MAAW,EDpE7C,cAAe,EAAE,GAAI,EACvB,6BAAgB,EACd,MAAO,EAAE,GAAI,EACf,iCAAoB,EAClB,MAAO,EAAE,GAAqB,EAC9B,eAAgB,EAAE,MAAkC,EACpD,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,IAAK,EACjB,QAAS,EAAE,EAAG,EACd,KAAM,EAAE,MAAO,EACf,IAAK,ECiD6B,MAAM,EJgC1C,IAAK,EAAE,AAAC,EACR,iFAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,uCAAO,EACL,IAAK,EAAE,GAAI,EGrFX,qCAAG,EACD,IAAK,EClB2B,MAAyB,EDmB3D,0CAAQ,EACN,IAAK,EAAE,GAAI,EACb,4CAAU,EACR,IAAK,EAAE,GAAI,EACb,iDAAiB,EACf,eAAgB,ECQgB,MAAI,EDPpC,IAAK,EC0B2B,GAAM,EDzBxC,wDAAwB,EACtB,eAAgB,ECXgB,MAAO,EDYvC,IAAK,ECzB2B,GAAI,ED0BxC,yCAA8B,EAC5B,MAAO,EAAE,IAAK,EAChB,gCAAmB,EACjB,QAAS,EAAE,EAAG,EACd,MAAO,EAAE,GAAqB,EAC9B,IAAK,ECE6B,GAAwB,EDD1D,MAAO,EAAE,GAAI,EACb,mCAAE,EACA,MAAO,EAAE,IAAK,EACd,KAAM,EAAE,EAAG,EACX,KAAM,EAAE,AAAC,EACT,KAAM,EAAE,KAAM,EACd,MAAO,EAAE,AAAC,EACV,SAAU,EAAE,gBAA6C,EAC3D,mCAAE,EACA,MAAO,EAAE,WAAY,EACrB,KAAM,EAAE,AAAC,EACT,qCAAC,EACC,MAAO,EAAE,WAAY,EACrB,MAAO,EAAE,EAAqB,EAC9B,IAAK,ECjDyB,MAAyB,EDkD7D,sBAAW,EACT,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,IAAK,EAAE,GAAI,EACX,GAAI,EAAE,GAAI,EACV,KAAM,EAAE,GAAI,EACZ,QAAS,ECkByB,IAAK,EDjBvC,iCAAU,EACR,IAAK,EAAE,GAAI,EACb,+BAAQ,EACN,IAAK,EAAE,GAAI,EACb,oDAA+B,EAC7B,SAAU,EAAE,IAAK,EACjB,6DAAQ,EACN,IAAK,EAAE,GAAI,EACb,+DAAU,EACR,IAAK,EAAE,GAAI,EACf,2CAAoB,EAClB,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,UAAW,EAAE,GAAI,EACjB,MAAO,EAAE,IAAuB,EAChC,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,KAAM,EGhDpB,mCAAsB,EHmDxB,YAAa,EACX,IAAK,EAAE,EAAG,EACV,MAAO,EAAE,GAAI,EACb,kBAAO,EACL,MAAO,EAAE,IAAK,EAClB,EAAG,EACD,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI",
|
||||
"sources": ["../../../bower_components/wyrm/sass/wyrm_core/_mixin.sass","../../../bower_components/bourbon/dist/css3/_font-face.scss","../../../sass/_theme_badge_fa.sass","../../../sass/_theme_badge.sass","../../../bower_components/wyrm/sass/wyrm_core/_wy_variables.sass","../../../sass/_theme_variables.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_media.scss"],
|
||||
"names": [],
|
||||
"file": "badge_only.css"
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
7
doc/_themes/sphinx_rtd_theme/static/css/theme.css.map
vendored
Normal file
7
doc/_themes/sphinx_rtd_theme/static/css/theme.css.map
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf
vendored
Normal file
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Inconsolata-Bold.ttf
vendored
Normal file
Binary file not shown.
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Inconsolata.ttf
vendored
Normal file
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Inconsolata.ttf
vendored
Normal file
Binary file not shown.
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf
vendored
Normal file
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Lato-Bold.ttf
vendored
Normal file
Binary file not shown.
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf
vendored
Normal file
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/Lato-Regular.ttf
vendored
Normal file
Binary file not shown.
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf
vendored
Normal file
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Bold.ttf
vendored
Normal file
Binary file not shown.
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf
vendored
Normal file
BIN
doc/_themes/sphinx_rtd_theme/static/fonts/RobotoSlab-Regular.ttf
vendored
Normal file
Binary file not shown.
4
doc/_themes/sphinx_rtd_theme/static/js/modernizr.min.js
vendored
Normal file
4
doc/_themes/sphinx_rtd_theme/static/js/modernizr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
108
doc/_themes/sphinx_rtd_theme/static/js/theme.js
vendored
108
doc/_themes/sphinx_rtd_theme/static/js/theme.js
vendored
@@ -1,47 +1,113 @@
|
||||
$( document ).ready(function() {
|
||||
function toggleCurrent (elem) {
|
||||
var parent_li = elem.closest('li');
|
||||
parent_li.siblings('li.current').removeClass('current');
|
||||
parent_li.siblings().find('li.current').removeClass('current');
|
||||
parent_li.find('> ul li.current').removeClass('current');
|
||||
parent_li.toggleClass('current');
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Shift nav in mobile when clicking the menu.
|
||||
$(document).on('click', "[data-toggle='wy-nav-top']", function() {
|
||||
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
});
|
||||
// Close menu when you click a link.
|
||||
// Nav menu link click operations
|
||||
$(document).on('click', ".wy-menu-vertical .current ul li a", function() {
|
||||
$("[data-toggle='wy-nav-shift']").removeClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
var target = $(this);
|
||||
// Close menu when you click a link.
|
||||
$("[data-toggle='wy-nav-shift']").removeClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
// Handle dynamic display of l3 and l4 nav lists
|
||||
toggleCurrent(target);
|
||||
if (typeof(window.SphinxRtdTheme) != 'undefined') {
|
||||
window.SphinxRtdTheme.StickyNav.hashChange();
|
||||
}
|
||||
});
|
||||
$(document).on('click', "[data-toggle='rst-current-version']", function() {
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift-up");
|
||||
});
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift-up");
|
||||
});
|
||||
// Make tables responsive
|
||||
$("table.docutils:not(.field-list)").wrap("<div class='wy-table-responsive'></div>");
|
||||
|
||||
// Add expand links to all parents of nested ul
|
||||
$('.wy-menu-vertical ul').siblings('a').each(function () {
|
||||
var link = $(this);
|
||||
expand = $('<span class="toctree-expand"></span>');
|
||||
expand.on('click', function (ev) {
|
||||
toggleCurrent(link);
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
link.prepend(expand);
|
||||
});
|
||||
});
|
||||
|
||||
// Sphinx theme state
|
||||
window.SphinxRtdTheme = (function (jquery) {
|
||||
var stickyNav = (function () {
|
||||
var navBar,
|
||||
win,
|
||||
stickyNavCssClass = 'stickynav',
|
||||
applyStickNav = function () {
|
||||
if (navBar.height() <= win.height()) {
|
||||
navBar.addClass(stickyNavCssClass);
|
||||
} else {
|
||||
navBar.removeClass(stickyNavCssClass);
|
||||
}
|
||||
},
|
||||
winScroll = false,
|
||||
linkScroll = false,
|
||||
winPosition = 0,
|
||||
enable = function () {
|
||||
applyStickNav();
|
||||
win.on('resize', applyStickNav);
|
||||
init();
|
||||
reset();
|
||||
win.on('hashchange', reset);
|
||||
|
||||
// Set scrolling
|
||||
win.on('scroll', function () {
|
||||
if (!linkScroll) {
|
||||
winScroll = true;
|
||||
}
|
||||
});
|
||||
setInterval(function () {
|
||||
if (winScroll) {
|
||||
winScroll = false;
|
||||
var newWinPosition = win.scrollTop(),
|
||||
navPosition = navBar.scrollTop(),
|
||||
newNavPosition = navPosition + (newWinPosition - winPosition);
|
||||
navBar.scrollTop(newNavPosition);
|
||||
winPosition = newWinPosition;
|
||||
}
|
||||
}, 25);
|
||||
},
|
||||
init = function () {
|
||||
navBar = jquery('nav.wy-nav-side:first');
|
||||
win = jquery(window);
|
||||
win = jquery(window);
|
||||
},
|
||||
reset = function () {
|
||||
// Get anchor from URL and open up nested nav
|
||||
var anchor = encodeURI(window.location.hash);
|
||||
if (anchor) {
|
||||
try {
|
||||
var link = $('.wy-menu-vertical')
|
||||
.find('[href="' + anchor + '"]');
|
||||
$('.wy-menu-vertical li.toctree-l1 li.current')
|
||||
.removeClass('current');
|
||||
link.closest('li.toctree-l2').addClass('current');
|
||||
link.closest('li.toctree-l3').addClass('current');
|
||||
link.closest('li.toctree-l4').addClass('current');
|
||||
}
|
||||
catch (err) {
|
||||
console.log("Error expanding nav for anchor", err);
|
||||
}
|
||||
}
|
||||
},
|
||||
hashChange = function () {
|
||||
linkScroll = true;
|
||||
win.one('hashchange', function () {
|
||||
linkScroll = false;
|
||||
});
|
||||
};
|
||||
jquery(init);
|
||||
return {
|
||||
enable : enable
|
||||
enable: enable,
|
||||
hashChange: hashChange
|
||||
};
|
||||
}());
|
||||
return {
|
||||
StickyNav : stickyNav
|
||||
StickyNav: stickyNav
|
||||
};
|
||||
}($));
|
||||
|
||||
1
doc/_themes/sphinx_rtd_theme/theme.conf
vendored
1
doc/_themes/sphinx_rtd_theme/theme.conf
vendored
@@ -6,3 +6,4 @@ stylesheet = css/theme.css
|
||||
typekit_id = hiw1hhg
|
||||
analytics_id =
|
||||
sticky_navigation = False
|
||||
logo_only =
|
||||
|
||||
@@ -8,7 +8,7 @@ _h2load()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--threads --connection-window-bits --input-file --help --requests --verbose --version --window-bits --clients --no-tls-proto --header --max-concurrent-streams ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--threads --connection-window-bits --input-file --help --requests --data --verbose --version --window-bits --clients --no-tls-proto --header --max-concurrent-streams ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttp()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--verbose --no-dep --get-assets --har --header-table-size --multiply --padding --dep-idle --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --padding --hexdump --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpd()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--error-gzip --push --header-table-size --htdocs --padding --verbose --version --help --daemon --verify-client --workers --no-tls --color --early-response --dh-param-file ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--error-gzip --push --header-table-size --trailer --htdocs --address --padding --verbose --version --help --hexdump --dh-param-file --daemon --verify-client --echo-upload --workers --no-tls --color --early-response --max-concurrent-streams ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpx()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--frontend-http2-connection-window-bits --worker-read-rate --frontend-no-tls --frontend-http2-dump-request-header --daemon --write-rate --altsvc --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --ciphers --verify-client-cacert --backend-keep-alive-timeout --strip-incoming-x-forwarded-for --errorlog-file --private-key-passwd-file --version --backlog --backend-http-proxy-uri --add-response-header --backend-write-timeout --backend-request-buffer --add-x-forwarded-for --write-burst --backend-http2-connection-window-bits --insecure --rlimit-nofile --backend-http2-window-bits --tls-proto-list --no-location-rewrite --padding --accesslog-syslog --conf --http2-max-concurrent-streams --client-proxy --worker-frontend-connections --cacert --frontend-read-timeout --worker-write-burst --npn-list --syslog-facility --backend-http1-connections-per-host --no-server-push --client --http2-bridge --no-via --user --stream-write-timeout --backend-response-buffer --http2-no-cookie-crumbling --backend-read-timeout --stream-read-timeout --workers --worker-read-burst --tls-ctx-per-worker --dh-param-file --errorlog-syslog --frontend --accesslog-file --http2-proxy --read-burst --accesslog-format --frontend-http2-window-bits --backend-no-tls --client-private-key-file --pid-file --client-cert-file --no-host-rewrite --log-level --worker-write-rate --help --backend-tls-sni-field --subcert --frontend-frame-debug --frontend-write-timeout --verify-client --read-rate --frontend-http2-read-timeout --backend-ipv4 --listener-disable-timeout --backend-ipv6 --backend ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--worker-read-rate --frontend-no-tls --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --verify-client-cacert --backend-request-buffer --backend-http2-connection-window-bits --conf --worker-write-burst --npn-list --fetch-ocsp-response-file --stream-read-timeout --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --frontend-http2-connection-window-bits --ciphers --strip-incoming-x-forwarded-for --daemon --backend-keep-alive-timeout --backend-http-proxy-uri --backend-http1-connections-per-host --rlimit-nofile --no-via --ocsp-update-interval --backend-write-timeout --client --http2-no-cookie-crumbling --worker-read-burst --client-proxy --http2-bridge --accesslog-format --errorlog-syslog --errorlog-file --http2-max-concurrent-streams --frontend-write-timeout --read-burst --backend-ipv4 --backend-ipv6 --backend --insecure --log-level --tls-proto-list --backend-http2-connections-per-worker --dh-param-file --worker-frontend-connections --header-field-buffer --no-server-push --no-location-rewrite --no-ocsp --backend-response-buffer --workers --frontend-http2-window-bits --no-host-rewrite --worker-write-rate --backend-tls-sni-field --subcert --help --frontend-frame-debug --pid-file --frontend-http2-dump-request-header --private-key-passwd-file --write-rate --altsvc --user --add-x-forwarded-for --syslog-facility --frontend-read-timeout --backlog --write-burst --backend-http2-window-bits --padding --stream-write-timeout --cacert --version --verify-client --backend-read-timeout --frontend --accesslog-file --http2-proxy --max-header-fields --backend-no-tls --client-private-key-file --client-cert-file --add-response-header --read-rate ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
64
doc/h2load.1
64
doc/h2load.1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "H2LOAD" "1" "March 27, 2015" "0.7.9" "nghttp2"
|
||||
.TH "H2LOAD" "1" "May 16, 2015" "1.0.0" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.
|
||||
@@ -71,7 +71,7 @@ Default: \fB1\fP
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-i, \-\-input\-file=<FILE>
|
||||
Path of a file with multiple URIs are seperated by EOLs.
|
||||
Path of a file with multiple URIs are separated by EOLs.
|
||||
This option will disable URIs getting from command\-line.
|
||||
If \(aq\-\(aq is given as <FILE>, URIs will be read from stdin.
|
||||
URIs are used in this order for each client. All URIs
|
||||
@@ -93,6 +93,8 @@ Default: \fBauto\fP
|
||||
.B \-w, \-\-window\-bits=<N>
|
||||
Sets the stream level initial window size to (2**<N>)\-1.
|
||||
For SPDY, 2**<N> is used instead.
|
||||
.sp
|
||||
Default: \fB30\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -101,6 +103,8 @@ Sets the connection level initial window size to
|
||||
(2**<N>)\-1. For SPDY, if <N> is strictly less than 16,
|
||||
this option is ignored. Otherwise 2**<N> is used for
|
||||
SPDY.
|
||||
.sp
|
||||
Default: \fB30\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -112,9 +116,9 @@ Add/Override a header to the requests.
|
||||
.B \-p, \-\-no\-tls\-proto=<PROTOID>
|
||||
Specify ALPN identifier of the protocol to be used when
|
||||
accessing http URI without SSL/TLS.
|
||||
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c\-14
|
||||
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c
|
||||
.sp
|
||||
Default: \fBh2c\-14\fP
|
||||
Default: \fBh2c\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -201,13 +205,63 @@ The maximum time taken for request and response.
|
||||
The mean time taken for request and response.
|
||||
.TP
|
||||
.B sd
|
||||
The standard deviation of the time for request and response.
|
||||
The standard deviation of the time taken for request and response.
|
||||
.TP
|
||||
.B +/\- sd
|
||||
The fraction of the number of requests within standard deviation
|
||||
range (mean +/\- sd) against total number of successful requests.
|
||||
.UNINDENT
|
||||
.TP
|
||||
.B time for connect
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B min
|
||||
The minimum time taken to connect to a server.
|
||||
.TP
|
||||
.B max
|
||||
The maximum time taken to connect to a server.
|
||||
.TP
|
||||
.B mean
|
||||
The mean time taken to connect to a server.
|
||||
.TP
|
||||
.B sd
|
||||
The standard deviation of the time taken to connect to a server.
|
||||
.TP
|
||||
.B +/\- sd
|
||||
The fraction of the number of connections within standard
|
||||
deviation range (mean +/\- sd) against total number of successful
|
||||
connections.
|
||||
.UNINDENT
|
||||
.TP
|
||||
.B time for 1st byte (of (decrypted in case of TLS) application data)
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B min
|
||||
The minimum time taken to get 1st byte from a server.
|
||||
.TP
|
||||
.B max
|
||||
The maximum time taken to get 1st byte from a server.
|
||||
.TP
|
||||
.B mean
|
||||
The mean time taken to get 1st byte from a server.
|
||||
.TP
|
||||
.B sd
|
||||
The standard deviation of the time taken to get 1st byte from a
|
||||
server.
|
||||
.TP
|
||||
.B +/\- sd
|
||||
The fraction of the number of connections within standard
|
||||
deviation range (mean +/\- sd) against total number of successful
|
||||
connections.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH FLOW CONTROL
|
||||
.sp
|
||||
h2load sets large flow control window by default, and effectively
|
||||
disables flow control to avoid under utilization of server
|
||||
performance. To set smaller flow control window, use \fI\%\-w\fP and
|
||||
\fI\%\-W\fP options. For example, use \fB\-w16 \-W16\fP to set default
|
||||
window size described in HTTP/2 and SPDY protocol specification.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
|
||||
|
||||
.. program:: h2load
|
||||
|
||||
h2load(1)
|
||||
=========
|
||||
|
||||
@@ -44,7 +48,7 @@ OPTIONS
|
||||
|
||||
.. option:: -i, --input-file=<FILE>
|
||||
|
||||
Path of a file with multiple URIs are seperated by EOLs.
|
||||
Path of a file with multiple URIs are separated by EOLs.
|
||||
This option will disable URIs getting from command-line.
|
||||
If '-' is given as <FILE>, URIs will be read from stdin.
|
||||
URIs are used in this order for each client. All URIs
|
||||
@@ -65,6 +69,8 @@ OPTIONS
|
||||
Sets the stream level initial window size to (2\*\*<N>)-1.
|
||||
For SPDY, 2**<N> is used instead.
|
||||
|
||||
Default: ``30``
|
||||
|
||||
.. option:: -W, --connection-window-bits=<N>
|
||||
|
||||
Sets the connection level initial window size to
|
||||
@@ -72,6 +78,8 @@ OPTIONS
|
||||
this option is ignored. Otherwise 2\*\*<N> is used for
|
||||
SPDY.
|
||||
|
||||
Default: ``30``
|
||||
|
||||
.. option:: -H, --header=<HEADER>
|
||||
|
||||
Add/Override a header to the requests.
|
||||
@@ -80,9 +88,9 @@ OPTIONS
|
||||
|
||||
Specify ALPN identifier of the protocol to be used when
|
||||
accessing http URI without SSL/TLS.
|
||||
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c-14
|
||||
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c
|
||||
|
||||
Default: ``h2c-14``
|
||||
Default: ``h2c``
|
||||
|
||||
.. option:: -d, --data=<FILE>
|
||||
|
||||
@@ -147,11 +155,49 @@ time for request
|
||||
mean
|
||||
The mean time taken for request and response.
|
||||
sd
|
||||
The standard deviation of the time for request and response.
|
||||
The standard deviation of the time taken for request and response.
|
||||
+/- sd
|
||||
The fraction of the number of requests within standard deviation
|
||||
range (mean +/- sd) against total number of successful requests.
|
||||
|
||||
time for connect
|
||||
min
|
||||
The minimum time taken to connect to a server.
|
||||
max
|
||||
The maximum time taken to connect to a server.
|
||||
mean
|
||||
The mean time taken to connect to a server.
|
||||
sd
|
||||
The standard deviation of the time taken to connect to a server.
|
||||
+/- sd
|
||||
The fraction of the number of connections within standard
|
||||
deviation range (mean +/- sd) against total number of successful
|
||||
connections.
|
||||
|
||||
time for 1st byte (of (decrypted in case of TLS) application data)
|
||||
min
|
||||
The minimum time taken to get 1st byte from a server.
|
||||
max
|
||||
The maximum time taken to get 1st byte from a server.
|
||||
mean
|
||||
The mean time taken to get 1st byte from a server.
|
||||
sd
|
||||
The standard deviation of the time taken to get 1st byte from a
|
||||
server.
|
||||
+/- sd
|
||||
The fraction of the number of connections within standard
|
||||
deviation range (mean +/- sd) against total number of successful
|
||||
connections.
|
||||
|
||||
FLOW CONTROL
|
||||
------------
|
||||
|
||||
h2load sets large flow control window by default, and effectively
|
||||
disables flow control to avoid under utilization of server
|
||||
performance. To set smaller flow control window, use :option:`-w` and
|
||||
:option:`-W` options. For example, use ``-w16 -W16`` to set default
|
||||
window size described in HTTP/2 and SPDY protocol specification.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -44,11 +44,49 @@ time for request
|
||||
mean
|
||||
The mean time taken for request and response.
|
||||
sd
|
||||
The standard deviation of the time for request and response.
|
||||
The standard deviation of the time taken for request and response.
|
||||
+/- sd
|
||||
The fraction of the number of requests within standard deviation
|
||||
range (mean +/- sd) against total number of successful requests.
|
||||
|
||||
time for connect
|
||||
min
|
||||
The minimum time taken to connect to a server.
|
||||
max
|
||||
The maximum time taken to connect to a server.
|
||||
mean
|
||||
The mean time taken to connect to a server.
|
||||
sd
|
||||
The standard deviation of the time taken to connect to a server.
|
||||
+/- sd
|
||||
The fraction of the number of connections within standard
|
||||
deviation range (mean +/- sd) against total number of successful
|
||||
connections.
|
||||
|
||||
time for 1st byte (of (decrypted in case of TLS) application data)
|
||||
min
|
||||
The minimum time taken to get 1st byte from a server.
|
||||
max
|
||||
The maximum time taken to get 1st byte from a server.
|
||||
mean
|
||||
The mean time taken to get 1st byte from a server.
|
||||
sd
|
||||
The standard deviation of the time taken to get 1st byte from a
|
||||
server.
|
||||
+/- sd
|
||||
The fraction of the number of connections within standard
|
||||
deviation range (mean +/- sd) against total number of successful
|
||||
connections.
|
||||
|
||||
FLOW CONTROL
|
||||
------------
|
||||
|
||||
h2load sets large flow control window by default, and effectively
|
||||
disables flow control to avoid under utilization of server
|
||||
performance. To set smaller flow control window, use :option:`-w` and
|
||||
:option:`-W` options. For example, use ``-w16 -W16`` to set default
|
||||
window size described in HTTP/2 and SPDY protocol specification.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
125
doc/mkapiref.py
125
doc/mkapiref.py
@@ -24,19 +24,21 @@
|
||||
|
||||
# Generates API reference from C source code.
|
||||
from __future__ import print_function # At least python 2.6 is required
|
||||
import re, sys, argparse
|
||||
import re, sys, argparse, os.path
|
||||
|
||||
class FunctionDoc:
|
||||
def __init__(self, name, content, domain):
|
||||
self.name = name
|
||||
self.content = content
|
||||
self.domain = domain
|
||||
if self.domain == 'function':
|
||||
self.funcname = re.search(r'(nghttp2_[^ )]+)\(', self.name).group(1)
|
||||
|
||||
def write(self, out):
|
||||
print('''.. {}:: {}'''.format(self.domain, self.name))
|
||||
print('')
|
||||
out.write('.. {}:: {}\n'.format(self.domain, self.name))
|
||||
out.write('\n')
|
||||
for line in self.content:
|
||||
print(' {}'.format(line))
|
||||
out.write(' {}\n'.format(line))
|
||||
|
||||
class StructDoc:
|
||||
def __init__(self, name, content, members, member_domain):
|
||||
@@ -47,17 +49,17 @@ class StructDoc:
|
||||
|
||||
def write(self, out):
|
||||
if self.name:
|
||||
print('''.. type:: {}'''.format(self.name))
|
||||
print('')
|
||||
out.write('.. type:: {}\n'.format(self.name))
|
||||
out.write('\n')
|
||||
for line in self.content:
|
||||
print(' {}'.format(line))
|
||||
print('')
|
||||
out.write(' {}\n'.format(line))
|
||||
out.write('\n')
|
||||
for name, content in self.members:
|
||||
print(''' .. {}:: {}'''.format(self.member_domain, name))
|
||||
print('')
|
||||
out.write(' .. {}:: {}\n'.format(self.member_domain, name))
|
||||
out.write('\n')
|
||||
for line in content:
|
||||
print(''' {}'''.format(line))
|
||||
print('')
|
||||
out.write(' {}\n'.format(line))
|
||||
out.write('\n')
|
||||
|
||||
class MacroDoc:
|
||||
def __init__(self, name, content):
|
||||
@@ -65,10 +67,10 @@ class MacroDoc:
|
||||
self.content = content
|
||||
|
||||
def write(self, out):
|
||||
print('''.. macro:: {}'''.format(self.name))
|
||||
print('')
|
||||
out.write('''.. macro:: {}\n'''.format(self.name))
|
||||
out.write('\n')
|
||||
for line in self.content:
|
||||
print(' {}'.format(line))
|
||||
out.write(' {}\n'.format(line))
|
||||
|
||||
def make_api_ref(infiles):
|
||||
macros = []
|
||||
@@ -93,19 +95,65 @@ def make_api_ref(infiles):
|
||||
enums.append(process_enum(infile))
|
||||
elif doctype == '@macro':
|
||||
macros.append(process_macro(infile))
|
||||
return macros, enums, types, functions
|
||||
|
||||
alldocs = [('Macros', macros),
|
||||
('Enums', enums),
|
||||
('Types (structs, unions and typedefs)', types),
|
||||
('Functions', functions)]
|
||||
for title, docs in alldocs:
|
||||
if not docs:
|
||||
continue
|
||||
print(title)
|
||||
print('-'*len(title))
|
||||
for doc in docs:
|
||||
doc.write(sys.stdout)
|
||||
print('')
|
||||
print('')
|
||||
|
||||
def output(
|
||||
indexfile, macrosfile, enumsfile, typesfile, funcsdir,
|
||||
macros, enums, types, functions):
|
||||
indexfile.write('''
|
||||
API Reference
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
macros
|
||||
enums
|
||||
types
|
||||
''')
|
||||
|
||||
for doc in functions:
|
||||
indexfile.write(' {}\n'.format(doc.funcname))
|
||||
|
||||
macrosfile.write('''
|
||||
Macros
|
||||
======
|
||||
''')
|
||||
for doc in macros:
|
||||
doc.write(macrosfile)
|
||||
|
||||
enumsfile.write('''
|
||||
Enums
|
||||
=====
|
||||
''')
|
||||
for doc in enums:
|
||||
doc.write(enumsfile)
|
||||
|
||||
typesfile.write('''
|
||||
Types (structs, unions and typedefs)
|
||||
====================================
|
||||
''')
|
||||
for doc in types:
|
||||
doc.write(typesfile)
|
||||
|
||||
for doc in functions:
|
||||
with open(os.path.join(funcsdir, doc.funcname + '.rst'), 'w') as f:
|
||||
f.write('''
|
||||
{funcname}
|
||||
{secul}
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
*#include <nghttp2/nghttp2.h>*
|
||||
|
||||
'''.format(funcname=doc.funcname, secul='='*len(doc.funcname)))
|
||||
doc.write(f)
|
||||
|
||||
def process_macro(infile):
|
||||
content = read_content(infile)
|
||||
@@ -174,6 +222,7 @@ def process_function(domain, infile):
|
||||
func_proto = ''.join(func_proto)
|
||||
func_proto = re.sub(r';\n$', '', func_proto)
|
||||
func_proto = re.sub(r'\s+', ' ', func_proto)
|
||||
func_proto = re.sub(r'NGHTTP2_EXTERN ', '', func_proto)
|
||||
return FunctionDoc(func_proto, content, domain)
|
||||
|
||||
def read_content(infile):
|
||||
@@ -199,12 +248,30 @@ def transform_content(content):
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="Generate API reference")
|
||||
parser.add_argument('--header', type=argparse.FileType('r'),
|
||||
help='header inserted at the top of the page')
|
||||
parser.add_argument('index', type=argparse.FileType('w'),
|
||||
help='index output file')
|
||||
parser.add_argument('macros', type=argparse.FileType('w'),
|
||||
help='macros section output file. The filename should be macros.rst')
|
||||
parser.add_argument('enums', type=argparse.FileType('w'),
|
||||
help='enums section output file. The filename should be enums.rst')
|
||||
parser.add_argument('types', type=argparse.FileType('w'),
|
||||
help='types section output file. The filename should be types.rst')
|
||||
parser.add_argument('funcsdir',
|
||||
help='functions doc output dir')
|
||||
parser.add_argument('files', nargs='+', type=argparse.FileType('r'),
|
||||
help='source file')
|
||||
args = parser.parse_args()
|
||||
if args.header:
|
||||
print(args.header.read())
|
||||
macros = []
|
||||
enums = []
|
||||
types = []
|
||||
funcs = []
|
||||
for infile in args.files:
|
||||
make_api_ref(args.files)
|
||||
m, e, t, f = make_api_ref(args.files)
|
||||
macros.extend(m)
|
||||
enums.extend(e)
|
||||
types.extend(t)
|
||||
funcs.extend(f)
|
||||
funcs.sort(key=lambda x: x.funcname)
|
||||
output(
|
||||
args.index, args.macros, args.enums, args.types, args.funcsdir,
|
||||
macros, enums, types, funcs)
|
||||
|
||||
85
doc/nghttp.1
85
doc/nghttp.1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTP" "1" "March 27, 2015" "0.7.9" "nghttp2"
|
||||
.TH "NGHTTP" "1" "May 16, 2015" "1.0.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 experimental client
|
||||
.
|
||||
@@ -64,8 +64,9 @@ yet.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-t, \-\-timeout=<SEC>
|
||||
Timeout each request after <SEC> seconds.
|
||||
.B \-t, \-\-timeout=<DURATION>
|
||||
Timeout each request after <DURATION>. Set 0 to disable
|
||||
timeout.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -104,8 +105,8 @@ Add a header to the requests. Example: \fI\%\-H\fP\(aq:method: PUT\(aq
|
||||
.B \-\-trailer=<HEADER>
|
||||
Add a trailer header to the requests. <HEADER> must not
|
||||
include pseudo header field (header field name starting
|
||||
with \(aq:\(aq). To send trailer, one must use \fI\-d\fP option to
|
||||
send request body. Example: \fI\-\-trailer\fP \(aqfoo: bar\(aq.
|
||||
with \(aq:\(aq). To send trailer, one must use \fI\%\-d\fP option to
|
||||
send request body. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -135,7 +136,7 @@ requested twice. This option disables it too.
|
||||
.TP
|
||||
.B \-u, \-\-upgrade
|
||||
Perform HTTP Upgrade for HTTP/2. This option is ignored
|
||||
if the request URI has https scheme. If \fI\-d\fP is used, the
|
||||
if the request URI has https scheme. If \fI\%\-d\fP is used, the
|
||||
HTTP upgrade request is performed with OPTIONS method.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@@ -192,11 +193,6 @@ Don\(aqt send dependency based priority hint to server.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-dep\-idle
|
||||
Use idle streams as anchor nodes to express priority.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-hexdump
|
||||
Display the incoming traffic in hexadecimal (Canonical
|
||||
hex+ASCII display). If SSL/TLS is used, decrypted data
|
||||
@@ -204,6 +200,11 @@ are used.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-push
|
||||
Disable server push.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-version
|
||||
Display version information and exit.
|
||||
.UNINDENT
|
||||
@@ -215,6 +216,68 @@ Display this help and exit.
|
||||
.sp
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
.sp
|
||||
The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
is omitted, a second is used as unit.
|
||||
.SH DEPENDENCY BASED PRIORITY
|
||||
.sp
|
||||
nghttp sends priority hints to server by default unless
|
||||
\fI\%\-\-no\-dep\fP is used. nghttp mimics the way Firefox employs to
|
||||
manages dependency using idle streams. We follows the behaviour of
|
||||
Firefox Nightly as of April, 2015, and nghttp\(aqs behaviour is very
|
||||
static and could be different from Firefox in detail. But reproducing
|
||||
the same behaviour of Firefox is not our goal. The goal is provide
|
||||
the easy way to test out the dependency priority in server
|
||||
implementation.
|
||||
.sp
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
+\-\-\-\-\-+
|
||||
|id=0 |
|
||||
+\-\-\-\-\-+
|
||||
^ ^ ^
|
||||
w=201 / | \e w=1
|
||||
/ | \e
|
||||
/ w=101| \e
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
|id=3 | |id=5 | |id=7 |
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
^ ^
|
||||
w=1 | w=1 |
|
||||
| |
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
|id=11| |id=9 |
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
In the above figure, \fBid\fP means stream ID, and \fBw\fP means weight.
|
||||
The stream 0 is non\-existence stream, and forms the root of the tree.
|
||||
The stream 7 and 9 are not used for now.
|
||||
.sp
|
||||
The URIs given in the command\-line depend on stream 11 with the weight
|
||||
given in \fI\%\-p\fP option, which defaults to 16.
|
||||
.sp
|
||||
If \fI\%\-a\fP option is used, nghttp parses the resource pointed by
|
||||
URI given in command\-line as html, and extracts resource links from
|
||||
it. When requesting those resources, nghttp uses dependency according
|
||||
to its resource type.
|
||||
.sp
|
||||
For CSS, and Javascript files inside "head" element, they depend on
|
||||
stream 3 with the weight 2. The Javascript files outside "head"
|
||||
element depend on stream 5 with the weight 2. The mages depend on
|
||||
stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
|
||||
|
||||
.. program:: nghttp
|
||||
|
||||
nghttp(1)
|
||||
=========
|
||||
|
||||
@@ -36,9 +40,10 @@ OPTIONS
|
||||
'index.html' is used as a filename. Not implemented
|
||||
yet.
|
||||
|
||||
.. option:: -t, --timeout=<SEC>
|
||||
.. option:: -t, --timeout=<DURATION>
|
||||
|
||||
Timeout each request after <SEC> seconds.
|
||||
Timeout each request after <DURATION>. Set 0 to disable
|
||||
timeout.
|
||||
|
||||
.. option:: -w, --window-bits=<N>
|
||||
|
||||
@@ -143,16 +148,16 @@ OPTIONS
|
||||
|
||||
Don't send dependency based priority hint to server.
|
||||
|
||||
.. option:: --dep-idle
|
||||
|
||||
Use idle streams as anchor nodes to express priority.
|
||||
|
||||
.. option:: --hexdump
|
||||
|
||||
Display the incoming traffic in hexadecimal (Canonical
|
||||
hex+ASCII display). If SSL/TLS is used, decrypted data
|
||||
are used.
|
||||
|
||||
.. option:: --no-push
|
||||
|
||||
Disable server push.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display version information and exit.
|
||||
@@ -162,9 +167,66 @@ OPTIONS
|
||||
Display this help and exit.
|
||||
|
||||
|
||||
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
|
||||
The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
is omitted, a second is used as unit.
|
||||
|
||||
DEPENDENCY BASED PRIORITY
|
||||
-------------------------
|
||||
|
||||
nghttp sends priority hints to server by default unless
|
||||
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
|
||||
manages dependency using idle streams. We follows the behaviour of
|
||||
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
|
||||
static and could be different from Firefox in detail. But reproducing
|
||||
the same behaviour of Firefox is not our goal. The goal is provide
|
||||
the easy way to test out the dependency priority in server
|
||||
implementation.
|
||||
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree::
|
||||
|
||||
+-----+
|
||||
|id=0 |
|
||||
+-----+
|
||||
^ ^ ^
|
||||
w=201 / | \ w=1
|
||||
/ | \
|
||||
/ w=101| \
|
||||
+-----+ +-----+ +-----+
|
||||
|id=3 | |id=5 | |id=7 |
|
||||
+-----+ +-----+ +-----+
|
||||
^ ^
|
||||
w=1 | w=1 |
|
||||
| |
|
||||
+-----+ +-----+
|
||||
|id=11| |id=9 |
|
||||
+-----+ +-----+
|
||||
|
||||
In the above figure, ``id`` means stream ID, and ``w`` means weight.
|
||||
The stream 0 is non-existence stream, and forms the root of the tree.
|
||||
The stream 7 and 9 are not used for now.
|
||||
|
||||
The URIs given in the command-line depend on stream 11 with the weight
|
||||
given in :option:`-p` option, which defaults to 16.
|
||||
|
||||
If :option:`-a` option is used, nghttp parses the resource pointed by
|
||||
URI given in command-line as html, and extracts resource links from
|
||||
it. When requesting those resources, nghttp uses dependency according
|
||||
to its resource type.
|
||||
|
||||
For CSS, and Javascript files inside "head" element, they depend on
|
||||
stream 3 with the weight 2. The Javascript files outside "head"
|
||||
element depend on stream 5 with the weight 2. The mages depend on
|
||||
stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -1,3 +1,54 @@
|
||||
DEPENDENCY BASED PRIORITY
|
||||
-------------------------
|
||||
|
||||
nghttp sends priority hints to server by default unless
|
||||
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
|
||||
manages dependency using idle streams. We follows the behaviour of
|
||||
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
|
||||
static and could be different from Firefox in detail. But reproducing
|
||||
the same behaviour of Firefox is not our goal. The goal is provide
|
||||
the easy way to test out the dependency priority in server
|
||||
implementation.
|
||||
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree::
|
||||
|
||||
+-----+
|
||||
|id=0 |
|
||||
+-----+
|
||||
^ ^ ^
|
||||
w=201 / | \ w=1
|
||||
/ | \
|
||||
/ w=101| \
|
||||
+-----+ +-----+ +-----+
|
||||
|id=3 | |id=5 | |id=7 |
|
||||
+-----+ +-----+ +-----+
|
||||
^ ^
|
||||
w=1 | w=1 |
|
||||
| |
|
||||
+-----+ +-----+
|
||||
|id=11| |id=9 |
|
||||
+-----+ +-----+
|
||||
|
||||
In the above figure, ``id`` means stream ID, and ``w`` means weight.
|
||||
The stream 0 is non-existence stream, and forms the root of the tree.
|
||||
The stream 7 and 9 are not used for now.
|
||||
|
||||
The URIs given in the command-line depend on stream 11 with the weight
|
||||
given in :option:`-p` option, which defaults to 16.
|
||||
|
||||
If :option:`-a` option is used, nghttp parses the resource pointed by
|
||||
URI given in command-line as html, and extracts resource links from
|
||||
it. When requesting those resources, nghttp uses dependency according
|
||||
to its resource type.
|
||||
|
||||
For CSS, and Javascript files inside "head" element, they depend on
|
||||
stream 3 with the weight 2. The Javascript files outside "head"
|
||||
element depend on stream 5 with the weight 2. The mages depend on
|
||||
stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPD" "1" "March 27, 2015" "0.7.9" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "May 16, 2015" "1.0.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 experimental server
|
||||
.
|
||||
@@ -63,7 +63,7 @@ address determined by getaddrinfo is used.
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-D, \-\-daemon
|
||||
Run in a background. If \fI\-D\fP is used, the current working
|
||||
Run in a background. If \fI\%\-D\fP is used, the current working
|
||||
directory is changed to \(aq\fI/\fP\(aq. Therefore if this option
|
||||
is used, \fI\%\-d\fP option must be specified.
|
||||
.UNINDENT
|
||||
@@ -109,7 +109,7 @@ Push resources <PUSH_PATH>s when <PATH> is requested.
|
||||
This option can be used repeatedly to specify multiple
|
||||
push configurations. <PATH> and <PUSH_PATH>s are
|
||||
relative to document root. See \fI\%\-\-htdocs\fP option.
|
||||
Example: \fI\-p\fP/=/foo.png \fI\-p\fP/doc=/bar.css
|
||||
Example: \fI\%\-p\fP/=/foo.png \fI\%\-p\fP/doc=/bar.css
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -119,6 +119,14 @@ Specify 0 to disable padding.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-m, \-\-max\-concurrent\-streams=<N>
|
||||
Set the maximum number of the concurrent streams in one
|
||||
HTTP/2 session.
|
||||
.sp
|
||||
Default: \fB100\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-n, \-\-workers=<N>
|
||||
Set the number of worker threads.
|
||||
.sp
|
||||
@@ -159,6 +167,11 @@ are used.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-echo\-upload
|
||||
Send back uploaded content if method is POST or PUT.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-version
|
||||
Display version information and exit.
|
||||
.UNINDENT
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
|
||||
|
||||
.. program:: nghttpd
|
||||
|
||||
nghttpd(1)
|
||||
==========
|
||||
|
||||
@@ -83,6 +87,13 @@ OPTIONS
|
||||
Add at most <N> bytes to a frame payload as padding.
|
||||
Specify 0 to disable padding.
|
||||
|
||||
.. option:: -m, --max-concurrent-streams=<N>
|
||||
|
||||
Set the maximum number of the concurrent streams in one
|
||||
HTTP/2 session.
|
||||
|
||||
Default: ``100``
|
||||
|
||||
.. option:: -n, --workers=<N>
|
||||
|
||||
Set the number of worker threads.
|
||||
@@ -117,6 +128,10 @@ OPTIONS
|
||||
hex+ASCII display). If SSL/TLS is used, decrypted data
|
||||
are used.
|
||||
|
||||
.. option:: --echo-upload
|
||||
|
||||
Send back uploaded content if method is POST or PUT.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display version information and exit.
|
||||
@@ -126,6 +141,7 @@ OPTIONS
|
||||
Display this help and exit.
|
||||
|
||||
|
||||
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPX" "1" "March 27, 2015" "0.7.9" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "May 16, 2015" "1.0.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 experimental proxy
|
||||
.
|
||||
@@ -46,7 +46,8 @@ Set path to server\(aqs private key. Required unless \fI\%\-p\fP,
|
||||
.TP
|
||||
.B <CERT>
|
||||
Set path to server\(aqs certificate. Required unless \fI\%\-p\fP,
|
||||
\fI\%\-\-client\fP or \fI\%\-\-frontend\-no\-tls\fP are given.
|
||||
\fI\%\-\-client\fP or \fI\%\-\-frontend\-no\-tls\fP are given. To make OCSP
|
||||
stapling work, this must be absolute path.
|
||||
.UNINDENT
|
||||
.SH OPTIONS
|
||||
.sp
|
||||
@@ -249,14 +250,14 @@ Default: \fB16K\fP
|
||||
Specify read timeout for HTTP/2 and SPDY frontend
|
||||
connection.
|
||||
.sp
|
||||
Default: \fB180s\fP
|
||||
Default: \fB3m\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-frontend\-read\-timeout=<DURATION>
|
||||
Specify read timeout for HTTP/1.1 frontend connection.
|
||||
.sp
|
||||
Default: \fB180s\fP
|
||||
Default: \fB3m\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -286,7 +287,7 @@ Default: \fB0\fP
|
||||
.B \-\-backend\-read\-timeout=<DURATION>
|
||||
Specify read timeout for backend connection.
|
||||
.sp
|
||||
Default: \fB180s\fP
|
||||
Default: \fB3m\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -348,7 +349,8 @@ password protected it\(aqll be requested interactively.
|
||||
Specify additional certificate and private key file.
|
||||
nghttpx will choose certificates based on the hostname
|
||||
indicated by client using TLS SNI extension. This
|
||||
option can be used multiple times.
|
||||
option can be used multiple times. To make OCSP
|
||||
stapling work, <CERTPATH> must be absolute path.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -433,14 +435,23 @@ are stored in memory.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-ctx\-per\-worker
|
||||
Create OpenSSL\(aqs SSL_CTX per worker, so that no internal
|
||||
locking is required. This may improve scalability with
|
||||
multi threaded configuration. If this option is
|
||||
enabled, session ID is no longer shared accross SSL_CTX
|
||||
objects, which means session ID generated by one worker
|
||||
is not acceptable by another worker. On the other hand,
|
||||
session ticket key is shared across all worker threads.
|
||||
.B \-\-fetch\-ocsp\-response\-file=<PATH>
|
||||
Path to fetch\-ocsp\-response script file. It should be
|
||||
absolute path.
|
||||
.sp
|
||||
Default: \fB/usr/local/share/nghttp2/fetch\-ocsp\-response\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-ocsp\-update\-interval=<DURATION>
|
||||
Set interval to update OCSP response cache.
|
||||
.sp
|
||||
Default: \fB4h\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-ocsp
|
||||
Disable OCSP stapling.
|
||||
.UNINDENT
|
||||
.SS HTTP/2 and SPDY
|
||||
.INDENT 0.0
|
||||
@@ -621,7 +632,8 @@ Default: \fB$remote_addr \- \- [$time_local] "$request" $status $body_bytes_sent
|
||||
.TP
|
||||
.B \-\-errorlog\-file=<PATH>
|
||||
Set path to write error log. To reopen file, send USR1
|
||||
signal to nghttpx.
|
||||
signal to nghttpx. stderr will be redirected to the
|
||||
error log file unless \fI\%\-\-errorlog\-syslog\fP is used.
|
||||
.sp
|
||||
Default: \fB/dev/stderr\fP
|
||||
.UNINDENT
|
||||
@@ -678,10 +690,10 @@ will not be altered regardless of this option.
|
||||
.B \-\-altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
|
||||
Specify protocol ID, port, host and origin of
|
||||
alternative service. <HOST> and <ORIGIN> are optional.
|
||||
They are advertised in alt\-svc header field or HTTP/2
|
||||
ALTSVC frame. This option can be used multiple times to
|
||||
specify multiple alternative services. Example:
|
||||
\fI\%\-\-altsvc\fP=h2,443
|
||||
They are advertised in alt\-svc header field only in
|
||||
HTTP/1.1 frontend. This option can be used multiple
|
||||
times to specify multiple alternative services.
|
||||
Example: \fI\%\-\-altsvc\fP=h2,443
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -692,6 +704,23 @@ won\(aqt replace anything already set. This option can be
|
||||
used several times to specify multiple header fields.
|
||||
Example: \fI\%\-\-add\-response\-header\fP="foo: bar"
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-header\-field\-buffer=<SIZE>
|
||||
Set maximum buffer size for incoming HTTP header field
|
||||
list. This is the sum of header name and value in
|
||||
bytes.
|
||||
.sp
|
||||
Default: \fB64K\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-max\-header\-fields=<N>
|
||||
Set maximum number of incoming HTTP header fields, which
|
||||
appear in one request or response header field list.
|
||||
.sp
|
||||
Default: \fB100\fP
|
||||
.UNINDENT
|
||||
.SS Debug
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -759,8 +788,9 @@ The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
.sp
|
||||
The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are s or ms. If
|
||||
a unit is omitted, a second is used as unit.
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
is omitted, a second is used as unit.
|
||||
.SH FILES
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -782,7 +812,7 @@ argument in the configuration file. Specify \fByes\fP as an argument
|
||||
ignored.
|
||||
.sp
|
||||
To specify private key and certificate file which are given as
|
||||
positional arguments in commnad\-line, use \fBprivate\-key\-file\fP and
|
||||
positional arguments in command\-line, use \fBprivate\-key\-file\fP and
|
||||
\fBcertificate\-file\fP\&.
|
||||
.sp
|
||||
\fI\%\-\-conf\fP option cannot be used in the configuration file and
|
||||
@@ -849,6 +879,15 @@ specified socket already exists in the file system, nghttpx first
|
||||
deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
.SH OCSP STAPLING
|
||||
.sp
|
||||
OCSP query is done using external perl script \fBfetch\-ocsp\-response\fP,
|
||||
which has been developed as part of h2o project
|
||||
(\fI\%https://github.com/h2o/h2o\fP).
|
||||
.sp
|
||||
The script file is usually installed under
|
||||
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
|
||||
be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fIh2load(1)\fP
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
|
||||
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
|
||||
|
||||
.. program:: nghttpx
|
||||
|
||||
nghttpx(1)
|
||||
==========
|
||||
|
||||
@@ -21,7 +25,8 @@ A reverse proxy for HTTP/2, HTTP/1 and SPDY.
|
||||
.. describe:: <CERT>
|
||||
|
||||
Set path to server's certificate. Required unless :option:`-p`\,
|
||||
:option:`--client` or :option:`\--frontend-no-tls` are given.
|
||||
:option:`--client` or :option:`\--frontend-no-tls` are given. To make OCSP
|
||||
stapling work, this must be absolute path.
|
||||
|
||||
|
||||
OPTIONS
|
||||
@@ -212,13 +217,13 @@ Timeout
|
||||
Specify read timeout for HTTP/2 and SPDY frontend
|
||||
connection.
|
||||
|
||||
Default: ``180s``
|
||||
Default: ``3m``
|
||||
|
||||
.. option:: --frontend-read-timeout=<DURATION>
|
||||
|
||||
Specify read timeout for HTTP/1.1 frontend connection.
|
||||
|
||||
Default: ``180s``
|
||||
Default: ``3m``
|
||||
|
||||
.. option:: --frontend-write-timeout=<DURATION>
|
||||
|
||||
@@ -244,7 +249,7 @@ Timeout
|
||||
|
||||
Specify read timeout for backend connection.
|
||||
|
||||
Default: ``180s``
|
||||
Default: ``3m``
|
||||
|
||||
.. option:: --backend-write-timeout=<DURATION>
|
||||
|
||||
@@ -301,7 +306,8 @@ SSL/TLS
|
||||
Specify additional certificate and private key file.
|
||||
nghttpx will choose certificates based on the hostname
|
||||
indicated by client using TLS SNI extension. This
|
||||
option can be used multiple times.
|
||||
option can be used multiple times. To make OCSP
|
||||
stapling work, <CERTPATH> must be absolute path.
|
||||
|
||||
.. option:: --backend-tls-sni-field=<HOST>
|
||||
|
||||
@@ -375,15 +381,22 @@ SSL/TLS
|
||||
automatically and renewed every 12hrs. At most 2 keys
|
||||
are stored in memory.
|
||||
|
||||
.. option:: --tls-ctx-per-worker
|
||||
.. option:: --fetch-ocsp-response-file=<PATH>
|
||||
|
||||
Create OpenSSL's SSL_CTX per worker, so that no internal
|
||||
locking is required. This may improve scalability with
|
||||
multi threaded configuration. If this option is
|
||||
enabled, session ID is no longer shared accross SSL_CTX
|
||||
objects, which means session ID generated by one worker
|
||||
is not acceptable by another worker. On the other hand,
|
||||
session ticket key is shared across all worker threads.
|
||||
Path to fetch-ocsp-response script file. It should be
|
||||
absolute path.
|
||||
|
||||
Default: ``/usr/local/share/nghttp2/fetch-ocsp-response``
|
||||
|
||||
.. option:: --ocsp-update-interval=<DURATION>
|
||||
|
||||
Set interval to update OCSP response cache.
|
||||
|
||||
Default: ``4h``
|
||||
|
||||
.. option:: --no-ocsp
|
||||
|
||||
Disable OCSP stapling.
|
||||
|
||||
|
||||
HTTP/2 and SPDY
|
||||
@@ -542,7 +555,8 @@ Logging
|
||||
.. option:: --errorlog-file=<PATH>
|
||||
|
||||
Set path to write error log. To reopen file, send USR1
|
||||
signal to nghttpx.
|
||||
signal to nghttpx. stderr will be redirected to the
|
||||
error log file unless :option:`--errorlog-syslog` is used.
|
||||
|
||||
Default: ``/dev/stderr``
|
||||
|
||||
@@ -594,10 +608,10 @@ HTTP
|
||||
|
||||
Specify protocol ID, port, host and origin of
|
||||
alternative service. <HOST> and <ORIGIN> are optional.
|
||||
They are advertised in alt-svc header field or HTTP/2
|
||||
ALTSVC frame. This option can be used multiple times to
|
||||
specify multiple alternative services. Example:
|
||||
:option:`--altsvc`\=h2,443
|
||||
They are advertised in alt-svc header field only in
|
||||
HTTP/1.1 frontend. This option can be used multiple
|
||||
times to specify multiple alternative services.
|
||||
Example: :option:`--altsvc`\=h2,443
|
||||
|
||||
.. option:: --add-response-header=<HEADER>
|
||||
|
||||
@@ -607,6 +621,21 @@ HTTP
|
||||
used several times to specify multiple header fields.
|
||||
Example: :option:`--add-response-header`\="foo: bar"
|
||||
|
||||
.. option:: --header-field-buffer=<SIZE>
|
||||
|
||||
Set maximum buffer size for incoming HTTP header field
|
||||
list. This is the sum of header name and value in
|
||||
bytes.
|
||||
|
||||
Default: ``64K``
|
||||
|
||||
.. option:: --max-header-fields=<N>
|
||||
|
||||
Set maximum number of incoming HTTP header fields, which
|
||||
appear in one request or response header field list.
|
||||
|
||||
Default: ``100``
|
||||
|
||||
|
||||
Debug
|
||||
~~~~~
|
||||
@@ -670,12 +699,14 @@ Misc
|
||||
Print this help and exit.
|
||||
|
||||
|
||||
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
|
||||
The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are s or ms. If
|
||||
a unit is omitted, a second is used as unit.
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
is omitted, a second is used as unit.
|
||||
|
||||
FILES
|
||||
-----
|
||||
@@ -698,7 +729,7 @@ FILES
|
||||
ignored.
|
||||
|
||||
To specify private key and certificate file which are given as
|
||||
positional arguments in commnad-line, use ``private-key-file`` and
|
||||
positional arguments in command-line, use ``private-key-file`` and
|
||||
``certificate-file``.
|
||||
|
||||
:option:`--conf` option cannot be used in the configuration file and
|
||||
@@ -763,6 +794,17 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external perl script ``fetch-ocsp-response``,
|
||||
which has been developed as part of h2o project
|
||||
(https://github.com/h2o/h2o).
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
be customized using :option:`--fetch-ocsp-response-file` option.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ FILES
|
||||
ignored.
|
||||
|
||||
To specify private key and certificate file which are given as
|
||||
positional arguments in commnad-line, use ``private-key-file`` and
|
||||
positional arguments in command-line, use ``private-key-file`` and
|
||||
``certificate-file``.
|
||||
|
||||
:option:`--conf` option cannot be used in the configuration file and
|
||||
@@ -84,6 +84,17 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external perl script ``fetch-ocsp-response``,
|
||||
which has been developed as part of h2o project
|
||||
(https://github.com/h2o/h2o).
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
be customized using :option:`--fetch-ocsp-response-file` option.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
API Reference
|
||||
=============
|
||||
Programmers' Guide
|
||||
==================
|
||||
|
||||
Includes
|
||||
--------
|
||||
@@ -20,17 +20,17 @@ nghttp2 callback functions directly or indirectly. It will lead to the
|
||||
crash. You can submit requests or frames in the callbacks then call
|
||||
these functions outside the callbacks.
|
||||
|
||||
Currently, `nghttp2_session_send()` and `nghttp2_session_mem_send()`
|
||||
do not send client connection preface
|
||||
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`). The applications are
|
||||
responsible to send it before sending any HTTP/2 frames using these
|
||||
functions if :type:`nghttp2_session` is configured as client.
|
||||
Similarly, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`
|
||||
do not consume client connection preface unless
|
||||
`nghttp2_option_set_recv_client_preface()` is used with nonzero option
|
||||
value. The applications are responsible to receive it before calling
|
||||
these functions if :type:`nghttp2_session` is configured as server and
|
||||
`nghttp2_option_set_recv_client_preface()` is not used.
|
||||
`nghttp2_session_send()` and `nghttp2_session_mem_send()` send first
|
||||
24 bytes of client magic string (MAGIC)
|
||||
(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
|
||||
applications are responsible to send SETTINGS frame as part of
|
||||
connection preface using `nghttp2_submit_settings()`. Similarly,
|
||||
`nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume
|
||||
MAGIC on server configuration unless
|
||||
`nghttp2_option_set_no_recv_client_magic()` is used with nonzero
|
||||
option value.
|
||||
|
||||
.. _http-messaging:
|
||||
|
||||
HTTP Messaging
|
||||
--------------
|
||||
@@ -50,8 +50,9 @@ Flow Control
|
||||
------------
|
||||
|
||||
HTTP/2 and SPDY/3 or later employ flow control and it may affect
|
||||
benchmarking results. To adjust receiver flow control window size,
|
||||
there is following options:
|
||||
benchmarking results. By default, h2load uses large enough flow
|
||||
control window, which effectively disables flow control. To adjust
|
||||
receiver flow control window size, there are following options:
|
||||
|
||||
``-w``
|
||||
Sets the stream level initial window size to
|
||||
@@ -86,5 +87,5 @@ If multiple URIs are specified, they are used in round robin manner.
|
||||
|
||||
.. note::
|
||||
|
||||
Please note that h2load uses sheme, host and port in the first URI
|
||||
Please note that h2load uses scheme, host and port in the first URI
|
||||
and ignores those parts in the rest of the URIs.
|
||||
|
||||
@@ -28,6 +28,7 @@ Contents:
|
||||
h2load.1
|
||||
nghttpx-howto
|
||||
h2load-howto
|
||||
programmers-guide
|
||||
apiref
|
||||
libnghttp2_asio
|
||||
python-apiref
|
||||
@@ -48,5 +49,5 @@ https://github.com/tatsuhiro-t/nghttp2/releases
|
||||
Resources
|
||||
---------
|
||||
|
||||
* http://tools.ietf.org/html/draft-ietf-httpbis-http2-14
|
||||
* http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
|
||||
* HTTP/2 https://tools.ietf.org/html/rfc7540
|
||||
* HPACK https://tools.ietf.org/html/rfc7541
|
||||
|
||||
@@ -80,7 +80,7 @@ status code, in the above example, which is 200. The second argument,
|
||||
which is omitted in the above example, is additional header fields to
|
||||
send.
|
||||
|
||||
``nghttp2::asio_http2::server::response::end`` sends responde body.
|
||||
``nghttp2::asio_http2::server::response::end`` sends response body.
|
||||
In the above example, we send string "hello, world".
|
||||
|
||||
The life time of req and res object ends after the callback set by
|
||||
@@ -277,7 +277,7 @@ response header fields and response body to the console screen:
|
||||
``boost::asio::io_service`` object and remote server address. When
|
||||
connection is made, the callback function passed to
|
||||
``nghttp2::asio_http2::client::on_connect`` is invoked with connected
|
||||
address as its paramter. After this callback call, use
|
||||
address as its parameter. After this callback call, use
|
||||
``nghttp2::asio_http2::session::submit`` to send request to the
|
||||
server. You can submit multiple requests at once without waiting for
|
||||
the completion of previous request.
|
||||
|
||||
@@ -21,7 +21,7 @@ SSL/TLS, the frontend also supports SPDY protocol.
|
||||
By default, this mode's frontend connection is encrypted using
|
||||
SSL/TLS. So server's private key and certificate must be supplied to
|
||||
the command line (or through configuration file). In this case, the
|
||||
fontend protocol selection will is done via ALPN or NPN.
|
||||
frontend protocol selection will is done via ALPN or NPN.
|
||||
|
||||
With ``--frontend-no-tls`` option, user can turn off SSL/TLS in
|
||||
frontend connection. In this case, SPDY protocol is not available
|
||||
@@ -243,7 +243,7 @@ Read/write rate limit
|
||||
---------------------
|
||||
|
||||
nghttpx supports transfer rate limiting on frontend connections. You
|
||||
can do rate limit per frontend connection for reading and writeing
|
||||
can do rate limit per frontend connection for reading and writing
|
||||
individually.
|
||||
|
||||
To perform rate limit for reading, use ``--read-rate`` and
|
||||
|
||||
@@ -220,6 +220,10 @@ HTTP/2 servers
|
||||
|
||||
This is a value of ``:path`` header field.
|
||||
|
||||
.. py:attribute:: headers
|
||||
|
||||
Request header fields.
|
||||
|
||||
A :py:class:`BaseRequestHandler` has the following methods:
|
||||
|
||||
.. py:method:: on_headers()
|
||||
@@ -249,10 +253,28 @@ HTTP/2 servers
|
||||
Send response. The *status* is HTTP status code. The *headers*
|
||||
is additional response headers. The *:status* header field will
|
||||
be appended by the library. The *body* is the response body.
|
||||
It could be ``None`` if response body is empty. Or it must be
|
||||
instance of either ``str``, ``bytes`` or :py:class:`io.IOBase`.
|
||||
If instance of ``str`` is specified, it will be encoded using
|
||||
UTF-8.
|
||||
It could be ``None`` if response body is empty. Or it must be
|
||||
instance of either ``str``, ``bytes``, :py:class:`io.IOBase` or
|
||||
callable, called body generator, which takes one parameter,
|
||||
size. The body generator generates response body. It can pause
|
||||
generation of response so that it can wait for slow backend data
|
||||
generation. When invoked, it should return tuple, byte string
|
||||
at most size length and flag. The flag is either
|
||||
:py:data:`DATA_OK`, :py:data:`DATA_EOF` or
|
||||
:py:data:`DATA_DEFERRED`. For non-empty byte string and it is
|
||||
not the last chunk of response, :py:data:`DATA_OK` must be
|
||||
returned as flag. If this is the last chunk of the response
|
||||
(byte string could be ``None``), :py:data:`DATA_EOF` must be
|
||||
returned as flag. If there is no data available right now, but
|
||||
additional data are anticipated, return tuple (``None``,
|
||||
:py:data:`DATA_DEFERRED`). When data arrived, call
|
||||
:py:meth:`resume()` and restart response body transmission.
|
||||
|
||||
Only the body generator can pause response body generation;
|
||||
instance of :py:class:`io.IOBase` must not block.
|
||||
|
||||
If instance of ``str`` is specified as *body*, it will be
|
||||
encoded using UTF-8.
|
||||
|
||||
The *headers* is a list of tuple of the form ``(name,
|
||||
value)``. The ``name`` and ``value`` can be either byte string
|
||||
@@ -273,10 +295,8 @@ HTTP/2 servers
|
||||
|
||||
The *status* is HTTP status code. The *headers* is additional
|
||||
response headers. The ``:status`` header field is appended by
|
||||
the library. The *body* is the response body. It could be
|
||||
``None`` if response body is empty. Or it must be instance of
|
||||
either ``str``, ``bytes`` or ``io.IOBase``. If instance of
|
||||
``str`` is specified, it is encoded using UTF-8.
|
||||
the library. The *body* is the response body. It has the same
|
||||
semantics of *body* parameter of :py:meth:`send_response()`.
|
||||
|
||||
The headers and request_headers are a list of tuple of the form
|
||||
``(name, value)``. The ``name`` and ``value`` can be either byte
|
||||
@@ -288,6 +308,27 @@ HTTP/2 servers
|
||||
|
||||
Raises the exception if any error occurs.
|
||||
|
||||
.. py:method:: resume()
|
||||
|
||||
Signals the restarting of response body transmission paused by
|
||||
``DATA_DEFERRED`` from the body generator (see
|
||||
:py:meth:`send_response()` about the body generator). It is not
|
||||
an error calling this method while response body transmission is
|
||||
not paused.
|
||||
|
||||
.. py:data:: DATA_OK
|
||||
|
||||
``DATA_OK`` indicates non empty data is generated from body generator.
|
||||
|
||||
.. py:data:: DATA_EOF
|
||||
|
||||
``DATA_EOF`` indicates the end of response body.
|
||||
|
||||
.. py:data:: DATA_DEFERRED
|
||||
|
||||
``DATA_DEFERRED`` indicates that data are not available right now
|
||||
and response should be paused.
|
||||
|
||||
The following example illustrates :py:class:`HTTP2Server` and
|
||||
:py:class:`BaseRequestHandler` usage:
|
||||
|
||||
@@ -296,6 +337,7 @@ The following example illustrates :py:class:`HTTP2Server` and
|
||||
#!/usr/bin/env python
|
||||
|
||||
import io, ssl
|
||||
|
||||
import nghttp2
|
||||
|
||||
class Handler(nghttp2.BaseRequestHandler):
|
||||
@@ -311,9 +353,85 @@ The following example illustrates :py:class:`HTTP2Server` and
|
||||
body=io.BytesIO(b'nghttp2-python FTW'))
|
||||
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2
|
||||
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
|
||||
ctx.load_cert_chain('server.crt', 'server.key')
|
||||
|
||||
# give None to ssl to make the server non-SSL/TLS
|
||||
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
|
||||
server.serve_forever()
|
||||
|
||||
The following example illustrates HTTP/2 server using asynchronous
|
||||
response body generation. This is simplified reverse proxy:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import ssl
|
||||
import os
|
||||
import urllib
|
||||
import asyncio
|
||||
import io
|
||||
|
||||
import nghttp2
|
||||
|
||||
@asyncio.coroutine
|
||||
def get_http_header(handler, url):
|
||||
url = urllib.parse.urlsplit(url)
|
||||
ssl = url.scheme == 'https'
|
||||
if url.port == None:
|
||||
if url.scheme == 'https':
|
||||
port = 443
|
||||
else:
|
||||
port = 80
|
||||
else:
|
||||
port = url.port
|
||||
|
||||
connect = asyncio.open_connection(url.hostname, port, ssl=ssl)
|
||||
reader, writer = yield from connect
|
||||
req = 'GET {path} HTTP/1.0\r\n\r\n'.format(path=url.path or '/')
|
||||
writer.write(req.encode('utf-8'))
|
||||
# skip response header fields
|
||||
while True:
|
||||
line = yield from reader.readline()
|
||||
line = line.rstrip()
|
||||
if not line:
|
||||
break
|
||||
# read body
|
||||
while True:
|
||||
b = yield from reader.read(4096)
|
||||
if not b:
|
||||
break
|
||||
handler.buf.write(b)
|
||||
writer.close()
|
||||
handler.buf.seek(0)
|
||||
handler.eof = True
|
||||
handler.resume()
|
||||
|
||||
class Body:
|
||||
def __init__(self, handler):
|
||||
self.handler = handler
|
||||
self.handler.eof = False
|
||||
self.handler.buf = io.BytesIO()
|
||||
|
||||
def generate(self, n):
|
||||
buf = self.handler.buf
|
||||
data = buf.read1(n)
|
||||
if not data and not self.handler.eof:
|
||||
return None, nghttp2.DATA_DEFERRED
|
||||
return data, nghttp2.DATA_EOF if self.handler.eof else nghttp2.DATA_OK
|
||||
|
||||
class Handler(nghttp2.BaseRequestHandler):
|
||||
|
||||
def on_headers(self):
|
||||
body = Body(self)
|
||||
asyncio.async(get_http_header(
|
||||
self, 'http://localhost' + self.path.decode('utf-8')))
|
||||
self.send_response(status=200, body=body.generate)
|
||||
|
||||
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
|
||||
ctx.load_cert_chain('server.crt', 'server.key')
|
||||
|
||||
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
|
||||
server.serve_forever()
|
||||
|
||||
@@ -65,11 +65,11 @@ its stream specific data in ``http2_stream_data`` structure and the
|
||||
defined as follows::
|
||||
|
||||
typedef struct {
|
||||
/* The NULL-terminated URI string to retreive. */
|
||||
/* The NULL-terminated URI string to retrieve. */
|
||||
const char *uri;
|
||||
/* Parsed result of the |uri| */
|
||||
struct http_parser_url *u;
|
||||
/* The authroity portion of the |uri|, not NULL-terminated */
|
||||
/* The authority portion of the |uri|, not NULL-terminated */
|
||||
char *authority;
|
||||
/* The path portion of the |uri|, including query, not
|
||||
NULL-terminated */
|
||||
@@ -184,9 +184,9 @@ its bufferevent, so it closes underlying connection as well. It also
|
||||
calls `nghttp2_session_del()` to delete nghttp2 session object.
|
||||
|
||||
We begin HTTP/2 communication by sending client connection preface,
|
||||
which is 24 bytes magic byte sequence
|
||||
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) and SETTINGS frame. The
|
||||
transmission of client connection header is done in
|
||||
which is 24 bytes magic byte string (:macro:`NGHTTP2_CLIENT_MAGIC`)
|
||||
followed by SETTINGS frame. First 24 bytes magic string is
|
||||
automatically sent by nghttp2 library. We send SETTINGS frame in
|
||||
``send_client_connection_header()``::
|
||||
|
||||
static void send_client_connection_header(http2_session_data *session_data) {
|
||||
@@ -194,8 +194,7 @@ transmission of client connection header is done in
|
||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||
int rv;
|
||||
|
||||
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
|
||||
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
|
||||
/* client 24 bytes magic string will be sent by nghttp2 library */
|
||||
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
|
||||
ARRLEN(iv));
|
||||
if (rv != 0) {
|
||||
@@ -204,7 +203,7 @@ transmission of client connection header is done in
|
||||
}
|
||||
|
||||
Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is
|
||||
really not needed for this tiny example progoram, but we are
|
||||
really not needed for this tiny example program, but we are
|
||||
demonstrating the use of SETTINGS frame. To queue the SETTINGS frame
|
||||
for the transmission, we use `nghttp2_submit_settings()`. Note that
|
||||
`nghttp2_submit_settings()` function only queues the frame and not
|
||||
@@ -388,7 +387,7 @@ After all name/value pairs are emitted for a frame,
|
||||
}
|
||||
|
||||
In this tutorial, we are just interested in the HTTP response
|
||||
HEADERS. We check te frame type and its category (it should be
|
||||
HEADERS. We check the frame type and its category (it should be
|
||||
:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check
|
||||
its stream ID.
|
||||
|
||||
@@ -407,7 +406,7 @@ of data is received from the remote peer::
|
||||
}
|
||||
|
||||
In our case, a chunk of data is response body. After checking stream
|
||||
ID, we just write the recieved data to the stdout. Note that the
|
||||
ID, we just write the received data to the stdout. Note that the
|
||||
output in the terminal may be corrupted if the response body contains
|
||||
some binary data.
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ bound of encoded result, use `nghttp2_hd_deflate_bound()` function::
|
||||
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
||||
const nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
Pass this function with the same paramters *deflater*, *nva* and
|
||||
Pass this function with the same parameters *deflater*, *nva* and
|
||||
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`.
|
||||
|
||||
The subsequent call of `nghttp2_hd_deflate_hd()` will use current
|
||||
|
||||
@@ -194,15 +194,8 @@ We initialize a nghttp2 session object which is done in
|
||||
``initialize_nghttp2_session()``::
|
||||
|
||||
static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
nghttp2_option *option;
|
||||
nghttp2_session_callbacks *callbacks;
|
||||
|
||||
nghttp2_option_new(&option);
|
||||
|
||||
/* Tells nghttp2_session object that it handles client connection
|
||||
preface */
|
||||
nghttp2_option_set_recv_client_preface(option, 1);
|
||||
|
||||
nghttp2_session_callbacks_new(&callbacks);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
@@ -219,20 +212,15 @@ We initialize a nghttp2 session object which is done in
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
|
||||
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
|
||||
option);
|
||||
nghttp2_session_server_new(&session_data->session, callbacks, session_data);
|
||||
|
||||
nghttp2_session_callbacks_del(callbacks);
|
||||
nghttp2_option_del(option);
|
||||
}
|
||||
|
||||
Since we are creating a server and uses options, the nghttp2 session
|
||||
object is created using `nghttp2_session_server_new2()` function. We
|
||||
registers five callbacks for nghttp2 session object. We'll talk about
|
||||
these callbacks later. Our server only speaks HTTP/2. In this case,
|
||||
we use `nghttp2_option_set_recv_client_preface()` to make
|
||||
:type:`nghttp2_session` object handle client connection preface, which
|
||||
saves some lines of application code.
|
||||
these callbacks later.
|
||||
|
||||
After initialization of the nghttp2 session object, we are going to send
|
||||
a server connection header in ``send_server_connection_header()``::
|
||||
|
||||
@@ -35,8 +35,12 @@
|
||||
//
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
@@ -28,16 +28,26 @@
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /* !HAVE_CONFIG_H */
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
@@ -528,14 +538,6 @@ static void fetch_uri(const struct URI *uri) {
|
||||
connection.ssl = ssl;
|
||||
connection.want_io = IO_NONE;
|
||||
|
||||
/* Send connection header in blocking I/O mode */
|
||||
rv = SSL_write(ssl, NGHTTP2_CLIENT_CONNECTION_PREFACE,
|
||||
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
|
||||
if (rv <= 0) {
|
||||
dief("SSL_write failed: could not send connection preface",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
|
||||
/* Here make file descriptor non-block */
|
||||
make_non_block(fd);
|
||||
set_tcp_nodelay(fd);
|
||||
|
||||
@@ -24,12 +24,18 @@
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /* !HAVE_CONFIG_H */
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#include <err.h>
|
||||
#include <signal.h>
|
||||
@@ -50,11 +56,11 @@
|
||||
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
typedef struct {
|
||||
/* The NULL-terminated URI string to retreive. */
|
||||
/* The NULL-terminated URI string to retrieve. */
|
||||
const char *uri;
|
||||
/* Parsed result of the |uri| */
|
||||
struct http_parser_url *u;
|
||||
/* The authroity portion of the |uri|, not NULL-terminated */
|
||||
/* The authority portion of the |uri|, not NULL-terminated */
|
||||
char *authority;
|
||||
/* The path portion of the |uri|, including query, not
|
||||
NULL-terminated */
|
||||
@@ -258,8 +264,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
|
||||
stream), if it is closed, we send GOAWAY and tear down the
|
||||
session */
|
||||
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code,
|
||||
void *user_data) {
|
||||
uint32_t error_code, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
int rv;
|
||||
|
||||
@@ -345,8 +350,7 @@ static void send_client_connection_header(http2_session_data *session_data) {
|
||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||
int rv;
|
||||
|
||||
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
|
||||
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
|
||||
/* client 24 bytes magic string will be sent by nghttp2 library */
|
||||
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
|
||||
ARRLEN(iv));
|
||||
if (rv != 0) {
|
||||
|
||||
@@ -24,17 +24,27 @@
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /* !HAVE_CONFIG_H */
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#include <err.h>
|
||||
|
||||
@@ -537,15 +547,8 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
||||
}
|
||||
|
||||
static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
nghttp2_option *option;
|
||||
nghttp2_session_callbacks *callbacks;
|
||||
|
||||
nghttp2_option_new(&option);
|
||||
|
||||
/* Tells nghttp2_session object that it handles client connection
|
||||
preface */
|
||||
nghttp2_option_set_recv_client_preface(option, 1);
|
||||
|
||||
nghttp2_session_callbacks_new(&callbacks);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
@@ -562,11 +565,9 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
|
||||
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
|
||||
option);
|
||||
nghttp2_session_server_new(&session_data->session, callbacks, session_data);
|
||||
|
||||
nghttp2_session_callbacks_del(callbacks);
|
||||
nghttp2_option_del(option);
|
||||
}
|
||||
|
||||
/* Send HTTP/2 client connection header, which includes 24 bytes
|
||||
|
||||
@@ -30,18 +30,30 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /* !HAVE_CONFIG_H */
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif /* HAVE_TIME_H */
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
@@ -153,7 +165,6 @@ const char *docroot;
|
||||
size_t docrootlen;
|
||||
|
||||
nghttp2_session_callbacks *shared_callbacks;
|
||||
nghttp2_option *shared_option;
|
||||
|
||||
static int handle_accept(io_loop *loop, uint32_t events, void *ptr);
|
||||
static int handle_connection(io_loop *loop, uint32_t events, void *ptr);
|
||||
@@ -190,7 +201,7 @@ typedef enum {
|
||||
NGHTTP2_TOKEN__METHOD,
|
||||
NGHTTP2_TOKEN__PATH,
|
||||
NGHTTP2_TOKEN__SCHEME,
|
||||
NGHTTP2_TOKEN_HOST,
|
||||
NGHTTP2_TOKEN_HOST
|
||||
} nghttp2_token;
|
||||
|
||||
/* Inspired by h2o header lookup. https://github.com/h2o/h2o */
|
||||
@@ -388,8 +399,7 @@ static connection *connection_new(int fd) {
|
||||
|
||||
conn = malloc(sizeof(connection));
|
||||
|
||||
rv = nghttp2_session_server_new2(&conn->session, shared_callbacks, conn,
|
||||
shared_option);
|
||||
rv = nghttp2_session_server_new(&conn->session, shared_callbacks, conn);
|
||||
|
||||
if (rv != 0) {
|
||||
goto cleanup;
|
||||
@@ -658,19 +668,52 @@ static void stream_error(connection *conn, int32_t stream_id,
|
||||
error_code);
|
||||
}
|
||||
|
||||
static int send_data_callback(nghttp2_session *session _U_,
|
||||
nghttp2_frame *frame, const uint8_t *framehd,
|
||||
size_t length, nghttp2_data_source *source,
|
||||
void *user_data) {
|
||||
connection *conn = user_data;
|
||||
uint8_t *p = conn->buf.last;
|
||||
stream *strm = source->ptr;
|
||||
|
||||
/* We never use padding in this program */
|
||||
assert(frame->data.padlen == 0);
|
||||
|
||||
if ((size_t)io_buf_left(&conn->buf) < 9 + frame->hd.length) {
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
}
|
||||
|
||||
memcpy(p, framehd, 9);
|
||||
p += 9;
|
||||
|
||||
while (length) {
|
||||
ssize_t nread;
|
||||
while ((nread = read(strm->filefd, p, length)) == -1 && errno == EINTR)
|
||||
;
|
||||
if (nread == -1) {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
length -= nread;
|
||||
p += nread;
|
||||
}
|
||||
|
||||
conn->buf.last = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t fd_read_callback(nghttp2_session *session _U_,
|
||||
int32_t stream_id _U_, uint8_t *buf,
|
||||
int32_t stream_id _U_, uint8_t *buf _U_,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data _U_) {
|
||||
stream *strm = source->ptr;
|
||||
ssize_t nread;
|
||||
ssize_t nread =
|
||||
(int64_t)length < strm->fileleft ? (int64_t)length : strm->fileleft;
|
||||
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
|
||||
|
||||
while ((nread = read(strm->filefd, buf, length)) == -1 && errno == EINTR)
|
||||
;
|
||||
if (nread == -1) {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
}
|
||||
strm->fileleft -= nread;
|
||||
if (nread == 0 || strm->fileleft == 0) {
|
||||
if (strm->fileleft != 0) {
|
||||
@@ -1274,14 +1317,8 @@ int main(int argc, char **argv) {
|
||||
shared_callbacks, on_stream_close_callback);
|
||||
nghttp2_session_callbacks_set_on_frame_not_send_callback(
|
||||
shared_callbacks, on_frame_not_send_callback);
|
||||
|
||||
rv = nghttp2_option_new(&shared_option);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "nghttp2_option_new: %s", nghttp2_strerror(rv));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
nghttp2_option_set_recv_client_preface(shared_option, 1);
|
||||
nghttp2_session_callbacks_set_send_data_callback(shared_callbacks,
|
||||
send_data_callback);
|
||||
|
||||
rv = io_loop_add(&loop, serv.fd, EPOLLIN, &serv);
|
||||
|
||||
@@ -1299,7 +1336,6 @@ int main(int argc, char **argv) {
|
||||
|
||||
io_loop_run(&loop, &serv);
|
||||
|
||||
nghttp2_option_del(shared_option);
|
||||
nghttp2_session_callbacks_del(shared_callbacks);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,19 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
HEADERS = [
|
||||
':authority',
|
||||
':method',
|
||||
':path',
|
||||
':scheme',
|
||||
':status',
|
||||
"content-length",
|
||||
"host",
|
||||
"te",
|
||||
'connection',
|
||||
'keep-alive',
|
||||
'proxy-connection',
|
||||
'transfer-encoding',
|
||||
'upgrade'
|
||||
(':authority', 0),
|
||||
(':method', 1),
|
||||
(':method', 2),
|
||||
(':path', 3),
|
||||
(':path', 4),
|
||||
(':scheme', 5),
|
||||
(':scheme', 6),
|
||||
(':status', 7),
|
||||
(':status', 8),
|
||||
(':status', 9),
|
||||
(':status', 10),
|
||||
(':status', 11),
|
||||
(':status', 12),
|
||||
(':status', 13),
|
||||
('accept-charset', 14),
|
||||
('accept-encoding', 15),
|
||||
('accept-language', 16),
|
||||
('accept-ranges', 17),
|
||||
('accept', 18),
|
||||
('access-control-allow-origin', 19),
|
||||
('age', 20),
|
||||
('allow', 21),
|
||||
('authorization', 22),
|
||||
('cache-control', 23),
|
||||
('content-disposition', 24),
|
||||
('content-encoding', 25),
|
||||
('content-language', 26),
|
||||
('content-length', 27),
|
||||
('content-location', 28),
|
||||
('content-range', 29),
|
||||
('content-type', 30),
|
||||
('cookie', 31),
|
||||
('date', 32),
|
||||
('etag', 33),
|
||||
('expect', 34),
|
||||
('expires', 35),
|
||||
('from', 36),
|
||||
('host', 37),
|
||||
('if-match', 38),
|
||||
('if-modified-since', 39),
|
||||
('if-none-match', 40),
|
||||
('if-range', 41),
|
||||
('if-unmodified-since', 42),
|
||||
('last-modified', 43),
|
||||
('link', 44),
|
||||
('location', 45),
|
||||
('max-forwards', 46),
|
||||
('proxy-authenticate', 47),
|
||||
('proxy-authorization', 48),
|
||||
('range', 49),
|
||||
('referer', 50),
|
||||
('refresh', 51),
|
||||
('retry-after', 52),
|
||||
('server', 53),
|
||||
('set-cookie', 54),
|
||||
('strict-transport-security', 55),
|
||||
('transfer-encoding', 56),
|
||||
('user-agent', 57),
|
||||
('vary', 58),
|
||||
('via', 59),
|
||||
('www-authenticate', 60),
|
||||
('te', None),
|
||||
('connection', None),
|
||||
('keep-alive',None),
|
||||
('proxy-connection', None),
|
||||
('upgrade', None),
|
||||
]
|
||||
|
||||
def to_enum_hd(k):
|
||||
@@ -27,7 +80,7 @@ def to_enum_hd(k):
|
||||
|
||||
def build_header(headers):
|
||||
res = {}
|
||||
for k in headers:
|
||||
for k, _ in headers:
|
||||
size = len(k)
|
||||
if size not in res:
|
||||
res[size] = {}
|
||||
@@ -40,18 +93,20 @@ def build_header(headers):
|
||||
return res
|
||||
|
||||
def gen_enum():
|
||||
print '''\
|
||||
typedef enum {'''
|
||||
for k in sorted(HEADERS):
|
||||
print '''\
|
||||
{},'''.format(to_enum_hd(k))
|
||||
print '''\
|
||||
NGHTTP2_TOKEN_MAXIDX,
|
||||
} nghttp2_token;'''
|
||||
name = ''
|
||||
print 'typedef enum {'
|
||||
for k, token in HEADERS:
|
||||
if token is None:
|
||||
print ' {},'.format(to_enum_hd(k))
|
||||
else:
|
||||
if name != k:
|
||||
name = k
|
||||
print ' {} = {},'.format(to_enum_hd(k), token)
|
||||
print '} nghttp2_token;'
|
||||
|
||||
def gen_index_header():
|
||||
print '''\
|
||||
static int lookup_token(const uint8_t *name, size_t namelen) {
|
||||
static inline int lookup_token(const uint8_t *name, size_t namelen) {
|
||||
switch (namelen) {'''
|
||||
b = build_header(HEADERS)
|
||||
for size in sorted(b.keys()):
|
||||
@@ -66,7 +121,7 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
|
||||
case '{}':'''.format(c)
|
||||
for k in headers:
|
||||
print '''\
|
||||
if (streq("{}", name, {})) {{
|
||||
if (lstreq("{}", name, {})) {{
|
||||
return {};
|
||||
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
|
||||
print '''\
|
||||
|
||||
13
help2rst.py
13
help2rst.py
@@ -61,6 +61,10 @@ def help2man(infile):
|
||||
description.append(line)
|
||||
|
||||
print '''
|
||||
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
|
||||
|
||||
.. program:: {cmdname}
|
||||
|
||||
{cmdname}(1)
|
||||
{cmdnameunderline}
|
||||
|
||||
@@ -78,6 +82,7 @@ DESCRIPTION
|
||||
synopsis=synopsis, description=format_text('\n'.join(description)))
|
||||
|
||||
in_arg = False
|
||||
in_footer = False
|
||||
|
||||
for line in infile:
|
||||
line = line.rstrip()
|
||||
@@ -95,6 +100,14 @@ DESCRIPTION
|
||||
print ''
|
||||
in_arg = False
|
||||
|
||||
if line == '--':
|
||||
in_footer = True
|
||||
continue
|
||||
|
||||
if in_footer:
|
||||
print line.strip()
|
||||
continue
|
||||
|
||||
if line == 'Options:':
|
||||
print 'OPTIONS'
|
||||
print '-------'
|
||||
|
||||
2
integration-tests/.gitignore
vendored
Normal file
2
integration-tests/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# generated files
|
||||
config.go
|
||||
@@ -246,6 +246,72 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H1HeaderFieldBufferPath tests that request with request path
|
||||
// larger than configured buffer size is rejected.
|
||||
func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
// The value 100 is chosen so that sum of header fields bytes
|
||||
// does not exceed it. We use > 100 bytes URI to exceed this
|
||||
// limit.
|
||||
st := newServerTester([]string{"--header-field-buffer=100"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H1HeaderFieldBufferPath",
|
||||
path: "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 431; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H1HeaderFieldBuffer tests that request with header fields
|
||||
// larger than configured buffer size is rejected.
|
||||
func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H1HeaderFieldBuffer",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 431; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H1HeaderFields tests that request with header fields more
|
||||
// than configured number is rejected.
|
||||
func TestH1H1HeaderFields(t *testing.T) {
|
||||
st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H1HeaderFields",
|
||||
header: []hpack.HeaderField{
|
||||
// Add extra header field to ensure that
|
||||
// header field limit exceeds
|
||||
pair("Connection", "close"),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 431; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H2ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/2 backend failed.
|
||||
func TestH1H2ConnectFailure(t *testing.T) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
@@ -494,7 +495,9 @@ func TestH2H1SNI(t *testing.T) {
|
||||
func TestH2H1ServerPush(t *testing.T) {
|
||||
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
// only resources marked as rel=preload are pushed
|
||||
w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
|
||||
if !strings.HasPrefix(r.URL.Path, "/css/") {
|
||||
w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
@@ -555,6 +558,79 @@ func TestH2H1RequestTrailer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1HeaderFieldBuffer tests that request with header fields
|
||||
// larger than configured buffer size is rejected.
|
||||
func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
||||
st := newServerTester([]string{"--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1HeaderFieldBuffer",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 431; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1HeaderFields tests that request with header fields more
|
||||
// than configured number is rejected.
|
||||
func TestH2H1HeaderFields(t *testing.T) {
|
||||
st := newServerTester([]string{"--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1HeaderFields",
|
||||
// we have at least 4 pseudo-header fields sent, and
|
||||
// that ensures that buffer limit exceeds.
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 431; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1Upgrade tests HTTP Upgrade to HTTP/2
|
||||
func TestH2H1Upgrade(t *testing.T) {
|
||||
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH2H1Upgrade",
|
||||
header: []hpack.HeaderField{
|
||||
pair("Connection", "Upgrade, HTTP2-Settings"),
|
||||
pair("Upgrade", "h2c"),
|
||||
pair("HTTP2-Settings", "AAMAAABkAAQAAP__"),
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, 101; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
res, err = st.http2(requestParam{
|
||||
httpUpgrade: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1GracefulShutdown tests graceful shutdown.
|
||||
func TestH2H1GracefulShutdown(t *testing.T) {
|
||||
st := newServerTester(nil, t, noopHandler)
|
||||
|
||||
@@ -170,6 +170,46 @@ func TestS3H1NoVia(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3H1HeaderFieldBuffer tests that request with header fields
|
||||
// larger than configured buffer size is rejected.
|
||||
func TestS3H1HeaderFieldBuffer(t *testing.T) {
|
||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3H1HeaderFieldBuffer",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
|
||||
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3H1HeaderFields tests that request with header fields more
|
||||
// than configured number is rejected.
|
||||
func TestS3H1HeaderFields(t *testing.T) {
|
||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--max-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3H1HeaderFields",
|
||||
// we have at least 5 pseudo-header fields sent, and
|
||||
// that ensures that buffer limit exceeds.
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
|
||||
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3H2ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/2 backend failed.
|
||||
func TestS3H2ConnectFailure(t *testing.T) {
|
||||
|
||||
@@ -247,15 +247,16 @@ func (st *serverTester) readSpdyFrame() (spdy.Frame, error) {
|
||||
}
|
||||
|
||||
type requestParam struct {
|
||||
name string // name for this request to identify the request in log easily
|
||||
streamID uint32 // stream ID, automatically assigned if 0
|
||||
method string // method, defaults to GET
|
||||
scheme string // scheme, defaults to http
|
||||
authority string // authority, defaults to backend server address
|
||||
path string // path, defaults to /
|
||||
header []hpack.HeaderField // additional request header fields
|
||||
body []byte // request body
|
||||
trailer []hpack.HeaderField // trailer part
|
||||
name string // name for this request to identify the request in log easily
|
||||
streamID uint32 // stream ID, automatically assigned if 0
|
||||
method string // method, defaults to GET
|
||||
scheme string // scheme, defaults to http
|
||||
authority string // authority, defaults to backend server address
|
||||
path string // path, defaults to /
|
||||
header []hpack.HeaderField // additional request header fields
|
||||
body []byte // request body
|
||||
trailer []hpack.HeaderField // trailer part
|
||||
httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade
|
||||
}
|
||||
|
||||
// wrapper for request body to set trailer part
|
||||
@@ -296,7 +297,19 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||
body = cbr
|
||||
}
|
||||
}
|
||||
req, err := http.NewRequest(method, st.url, body)
|
||||
|
||||
reqURL := st.url
|
||||
|
||||
if rp.path != "" {
|
||||
u, err := url.Parse(st.url)
|
||||
if err != nil {
|
||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||
}
|
||||
u.Path = rp.path
|
||||
reqURL = u.String()
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, reqURL, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -478,69 +491,70 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
streams := make(map[uint32]*serverResponse)
|
||||
streams[id] = res
|
||||
|
||||
method := "GET"
|
||||
if rp.method != "" {
|
||||
method = rp.method
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":method", method))
|
||||
|
||||
scheme := "http"
|
||||
if rp.scheme != "" {
|
||||
scheme = rp.scheme
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":scheme", scheme))
|
||||
|
||||
authority := st.authority
|
||||
if rp.authority != "" {
|
||||
authority = rp.authority
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":authority", authority))
|
||||
|
||||
path := "/"
|
||||
if rp.path != "" {
|
||||
path = rp.path
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":path", path))
|
||||
|
||||
_ = st.enc.WriteField(pair("test-case", rp.name))
|
||||
|
||||
for _, h := range rp.header {
|
||||
_ = st.enc.WriteField(h)
|
||||
}
|
||||
|
||||
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: id,
|
||||
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
|
||||
EndHeaders: true,
|
||||
BlockFragment: st.headerBlkBuf.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(rp.body) != 0 {
|
||||
// TODO we assume rp.body fits in 1 frame
|
||||
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
|
||||
return nil, err
|
||||
if !rp.httpUpgrade {
|
||||
method := "GET"
|
||||
if rp.method != "" {
|
||||
method = rp.method
|
||||
}
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":method", method))
|
||||
|
||||
if len(rp.trailer) != 0 {
|
||||
st.headerBlkBuf.Reset()
|
||||
for _, h := range rp.trailer {
|
||||
scheme := "http"
|
||||
if rp.scheme != "" {
|
||||
scheme = rp.scheme
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":scheme", scheme))
|
||||
|
||||
authority := st.authority
|
||||
if rp.authority != "" {
|
||||
authority = rp.authority
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":authority", authority))
|
||||
|
||||
path := "/"
|
||||
if rp.path != "" {
|
||||
path = rp.path
|
||||
}
|
||||
_ = st.enc.WriteField(pair(":path", path))
|
||||
|
||||
_ = st.enc.WriteField(pair("test-case", rp.name))
|
||||
|
||||
for _, h := range rp.header {
|
||||
_ = st.enc.WriteField(h)
|
||||
}
|
||||
|
||||
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: id,
|
||||
EndStream: true,
|
||||
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
|
||||
EndHeaders: true,
|
||||
BlockFragment: st.headerBlkBuf.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(rp.body) != 0 {
|
||||
// TODO we assume rp.body fits in 1 frame
|
||||
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(rp.trailer) != 0 {
|
||||
st.headerBlkBuf.Reset()
|
||||
for _, h := range rp.trailer {
|
||||
_ = st.enc.WriteField(h)
|
||||
}
|
||||
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: id,
|
||||
EndStream: true,
|
||||
EndHeaders: true,
|
||||
BlockFragment: st.headerBlkBuf.Bytes(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
loop:
|
||||
for {
|
||||
fr, err := st.readFrame()
|
||||
|
||||
3
lib/.gitignore
vendored
Normal file
3
lib/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# generated files
|
||||
includes/nghttp2/nghttp2ver.h
|
||||
libnghttp2.pc
|
||||
@@ -2,15 +2,14 @@
|
||||
# GNU Makefile for nghttp2 / MSVC.
|
||||
#
|
||||
# By G. Vanem <gvanem@yahoo.no> 2013
|
||||
# Updated 3/2015 by Remo Eichenberger @remoe
|
||||
# The MIT License apply.
|
||||
#
|
||||
|
||||
#
|
||||
# Choose your weapons:
|
||||
# Set 'ZLIB_ROOT' to the root of zlib.
|
||||
# Set 'USE_CYTHON=1' to build and install the 'nghttp2.pyd' Python extension.
|
||||
#
|
||||
ZLIB_ROOT = g:/MingW32/src/Compression/zlib-1.2.8
|
||||
USE_CYTHON = 1
|
||||
|
||||
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g')
|
||||
@@ -38,7 +37,7 @@ INSTALL_HDR = $(VC_ROOT)/include
|
||||
TARGETS = nghttp2.lib nghttp2.dll nghttp2_imp.lib \
|
||||
nghttp2d.lib nghttp2d.dll nghttp2d_imp.lib
|
||||
|
||||
EXT_LIBS = $(ZLIB_ROOT)/zlib.lib ws2_32.lib
|
||||
EXT_LIBS =
|
||||
|
||||
OBJ_DIR = MSVC_obj
|
||||
|
||||
@@ -46,32 +45,34 @@ NGHTTP2_PDB_R = $(OBJ_DIR)/nghttp2.pdb
|
||||
NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb
|
||||
|
||||
CC = cl
|
||||
CFLAGS = -I./includes -I$(ZLIB_ROOT) -DHAVE_WINSOCK2_H -Dssize_t=long
|
||||
CFLAGS = -I./includes -Dssize_t=long -D_U_=""
|
||||
|
||||
CFLAGS_R = -nologo -MD -W3 -Zi -Fd./$(NGHTTP2_PDB_R)
|
||||
CFLAGS_D = -nologo -MDd -W3 -Zi -Fd./$(NGHTTP2_PDB_D) \
|
||||
-Ot -D_DEBUG -GF -RTCs -RTCu # -RTCc -GS
|
||||
|
||||
LDFLAGS = -nologo -machine:i386 -map -debug -incremental:no # -verbose
|
||||
LDFLAGS = -nologo -machine:x64 -map -debug -incremental:no # -verbose
|
||||
|
||||
NGHTTP2_SRC = nghttp2_buf.c \
|
||||
nghttp2_callbacks.c \
|
||||
nghttp2_frame.c \
|
||||
nghttp2_helper.c \
|
||||
nghttp2_hd.c \
|
||||
nghttp2_hd_huffman.c \
|
||||
nghttp2_hd_huffman_data.c \
|
||||
nghttp2_map.c \
|
||||
nghttp2_npn.c \
|
||||
nghttp2_option.c \
|
||||
nghttp2_outbound_item.c \
|
||||
nghttp2_priority_spec.c \
|
||||
nghttp2_pq.c \
|
||||
nghttp2_queue.c \
|
||||
nghttp2_session.c \
|
||||
nghttp2_stream.c \
|
||||
nghttp2_submit.c \
|
||||
nghttp2_version.c
|
||||
NGHTTP2_SRC = nghttp2_pq.c \
|
||||
nghttp2_map.c \
|
||||
nghttp2_queue.c \
|
||||
nghttp2_frame.c \
|
||||
nghttp2_buf.c \
|
||||
nghttp2_stream.c \
|
||||
nghttp2_outbound_item.c \
|
||||
nghttp2_session.c \
|
||||
nghttp2_submit.c \
|
||||
nghttp2_helper.c \
|
||||
nghttp2_npn.c \
|
||||
nghttp2_hd.c \
|
||||
nghttp2_hd_huffman.c \
|
||||
nghttp2_hd_huffman_data.c \
|
||||
nghttp2_version.c \
|
||||
nghttp2_priority_spec.c \
|
||||
nghttp2_option.c \
|
||||
nghttp2_callbacks.c \
|
||||
nghttp2_mem.c \
|
||||
nghttp2_http.c
|
||||
|
||||
NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
|
||||
NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
|
||||
@@ -116,13 +117,13 @@ nghttp2d.lib: $(NGHTTP2_OBJ_D)
|
||||
lib -nologo -out:$@ $^
|
||||
@echo
|
||||
|
||||
nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(OBJ_DIR)/r_nghttp2.def
|
||||
link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib -def:$(OBJ_DIR)/r_nghttp2.def \
|
||||
nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res
|
||||
link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib \
|
||||
$(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS)
|
||||
@echo
|
||||
|
||||
nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(OBJ_DIR)/d_nghttp2.def
|
||||
link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib -def:$(OBJ_DIR)/d_nghttp2.def \
|
||||
nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res
|
||||
link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib \
|
||||
$(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS)
|
||||
@echo
|
||||
|
||||
@@ -219,24 +220,6 @@ nghttp2.rc: Makefile.MSVC
|
||||
@echo ' */' >> $@
|
||||
@echo "$$RES_FILE" >> $@
|
||||
|
||||
$(OBJ_DIR)/r_nghttp2.def: Makefile.MSVC
|
||||
@echo 'Generating $@...'
|
||||
@echo '; $(GENERATED). DO NOT EDIT.' > $@
|
||||
@echo ';' >> $@
|
||||
@echo 'LIBRARY nghttp2.dll' >> $@
|
||||
@echo 'EXPORTS' >> $@
|
||||
nm $(NGHTTP2_OBJ_R) | grep ' T .*_nghttp2' | sed 's/^.* _/ /' >> $@
|
||||
@echo 'NGHTTP2_STATIC_TABLE_LENGTH DATA' >> $@
|
||||
|
||||
$(OBJ_DIR)/d_nghttp2.def: Makefile.MSVC
|
||||
@echo 'Generating $@...'
|
||||
@echo '; $(GENERATED). DO NOT EDIT.' > $@
|
||||
@echo ';' >> $@
|
||||
@echo 'LIBRARY nghttp2d.dll' >> $@
|
||||
@echo 'EXPORTS' >> $@
|
||||
nm $(NGHTTP2_OBJ_D) | grep ' T .*_nghttp2' | sed 's/^.* _/ /' >> $@
|
||||
@echo 'NGHTTP2_STATIC_TABLE_LENGTH DATA' >> $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \
|
||||
nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h
|
||||
@@ -263,4 +246,4 @@ depend: includes/nghttp2/nghttp2ver.h
|
||||
sed -e $(REPLACE_D) .depend.tmp >> .depend.MSVC
|
||||
rm -f .depend.tmp
|
||||
|
||||
-include .depend.MSVC
|
||||
-include .depend.MSVC
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -320,7 +320,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
|
||||
}
|
||||
|
||||
buf->last = nghttp2_cpymem(buf->last, p, nwrite);
|
||||
p += len;
|
||||
p += nwrite;
|
||||
len -= nwrite;
|
||||
}
|
||||
|
||||
@@ -432,6 +432,24 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
||||
return (ssize_t)len;
|
||||
}
|
||||
|
||||
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
|
||||
size_t len;
|
||||
nghttp2_buf_chain *chain;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_buf resbuf;
|
||||
|
||||
len = nghttp2_bufs_len(bufs);
|
||||
|
||||
nghttp2_buf_wrap_init(&resbuf, out, len);
|
||||
|
||||
for (chain = bufs->head; chain; chain = chain->next) {
|
||||
buf = &chain->buf;
|
||||
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
|
||||
nghttp2_buf_chain *chain, *ci;
|
||||
size_t k;
|
||||
|
||||
@@ -324,6 +324,17 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
|
||||
*/
|
||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
|
||||
|
||||
/*
|
||||
* Copies all data stored in |bufs| to |out|. This function assumes
|
||||
* that the buffer space pointed by |out| has at least
|
||||
* nghttp2_bufs(bufs) bytes.
|
||||
*
|
||||
* The contents of |bufs| is left unchanged.
|
||||
*
|
||||
* This function returns the length of copied data.
|
||||
*/
|
||||
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
|
||||
|
||||
/*
|
||||
* Resets |bufs| and makes the buffers empty.
|
||||
*/
|
||||
|
||||
@@ -121,3 +121,9 @@ void nghttp2_session_callbacks_set_on_begin_frame_callback(
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
||||
cbs->on_begin_frame_callback = on_begin_frame_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_send_data_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_send_data_callback send_data_callback) {
|
||||
cbs->send_data_callback = send_data_callback;
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ struct nghttp2_session_callbacks {
|
||||
* Sets callback function invoked when a frame header is received.
|
||||
*/
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback;
|
||||
nghttp2_send_data_callback send_data_callback;
|
||||
};
|
||||
|
||||
#endif /* NGHTTP2_CALLBACKS_H */
|
||||
|
||||
@@ -813,7 +813,7 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
|
||||
static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
|
||||
size_t trail_padlen;
|
||||
size_t newlen;
|
||||
|
||||
@@ -828,6 +828,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
|
||||
newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen;
|
||||
nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3]));
|
||||
|
||||
if (framehd_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
trail_padlen = padlen - 1;
|
||||
buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen;
|
||||
|
||||
@@ -836,12 +840,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
|
||||
/* extend buffers trail_padlen bytes, since we ate previous padlen -
|
||||
trail_padlen byte(s) */
|
||||
buf->last += trail_padlen;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen) {
|
||||
size_t padlen, int framehd_only) {
|
||||
nghttp2_buf *buf;
|
||||
|
||||
if (padlen == 0) {
|
||||
@@ -874,7 +876,7 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
|
||||
assert(nghttp2_buf_avail(buf) >= (ssize_t)padlen - 1);
|
||||
|
||||
frame_set_pad(buf, padlen);
|
||||
frame_set_pad(buf, padlen, framehd_only);
|
||||
|
||||
hd->length += padlen;
|
||||
hd->flags |= NGHTTP2_FLAG_PADDED;
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
#define NGHTTP2_MAX_PADLEN 256
|
||||
|
||||
/* Union of extension frame payload */
|
||||
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload;
|
||||
typedef union { int dummy; } nghttp2_ext_frame_payload;
|
||||
|
||||
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
|
||||
|
||||
@@ -510,7 +510,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||
* Sets Pad Length field and flags and adjusts frame header position
|
||||
* of each buffers in |bufs|. The number of padding is given in the
|
||||
* |padlen| including Pad Length field. The |hd| is the frame header
|
||||
* for the serialized data.
|
||||
* for the serialized data. This function fills zeros padding region
|
||||
* unless framehd_only is nonzero.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -521,6 +522,6 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||
* The length of the resulting frame is too large.
|
||||
*/
|
||||
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen);
|
||||
size_t padlen, int framehd_only);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
|
||||
899
lib/nghttp2_hd.c
899
lib/nghttp2_hd.c
File diff suppressed because it is too large
Load Diff
103
lib/nghttp2_hd.h
103
lib/nghttp2_hd.h
@@ -49,7 +49,68 @@
|
||||
#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
|
||||
|
||||
/* Exported for unit test */
|
||||
extern const size_t NGHTTP2_STATIC_TABLE_LENGTH;
|
||||
#define NGHTTP2_STATIC_TABLE_LENGTH 61
|
||||
|
||||
/* Generated by genlibtokenlookup.py */
|
||||
typedef enum {
|
||||
NGHTTP2_TOKEN__AUTHORITY = 0,
|
||||
NGHTTP2_TOKEN__METHOD = 1,
|
||||
NGHTTP2_TOKEN__PATH = 3,
|
||||
NGHTTP2_TOKEN__SCHEME = 5,
|
||||
NGHTTP2_TOKEN__STATUS = 7,
|
||||
NGHTTP2_TOKEN_ACCEPT_CHARSET = 14,
|
||||
NGHTTP2_TOKEN_ACCEPT_ENCODING = 15,
|
||||
NGHTTP2_TOKEN_ACCEPT_LANGUAGE = 16,
|
||||
NGHTTP2_TOKEN_ACCEPT_RANGES = 17,
|
||||
NGHTTP2_TOKEN_ACCEPT = 18,
|
||||
NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 19,
|
||||
NGHTTP2_TOKEN_AGE = 20,
|
||||
NGHTTP2_TOKEN_ALLOW = 21,
|
||||
NGHTTP2_TOKEN_AUTHORIZATION = 22,
|
||||
NGHTTP2_TOKEN_CACHE_CONTROL = 23,
|
||||
NGHTTP2_TOKEN_CONTENT_DISPOSITION = 24,
|
||||
NGHTTP2_TOKEN_CONTENT_ENCODING = 25,
|
||||
NGHTTP2_TOKEN_CONTENT_LANGUAGE = 26,
|
||||
NGHTTP2_TOKEN_CONTENT_LENGTH = 27,
|
||||
NGHTTP2_TOKEN_CONTENT_LOCATION = 28,
|
||||
NGHTTP2_TOKEN_CONTENT_RANGE = 29,
|
||||
NGHTTP2_TOKEN_CONTENT_TYPE = 30,
|
||||
NGHTTP2_TOKEN_COOKIE = 31,
|
||||
NGHTTP2_TOKEN_DATE = 32,
|
||||
NGHTTP2_TOKEN_ETAG = 33,
|
||||
NGHTTP2_TOKEN_EXPECT = 34,
|
||||
NGHTTP2_TOKEN_EXPIRES = 35,
|
||||
NGHTTP2_TOKEN_FROM = 36,
|
||||
NGHTTP2_TOKEN_HOST = 37,
|
||||
NGHTTP2_TOKEN_IF_MATCH = 38,
|
||||
NGHTTP2_TOKEN_IF_MODIFIED_SINCE = 39,
|
||||
NGHTTP2_TOKEN_IF_NONE_MATCH = 40,
|
||||
NGHTTP2_TOKEN_IF_RANGE = 41,
|
||||
NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE = 42,
|
||||
NGHTTP2_TOKEN_LAST_MODIFIED = 43,
|
||||
NGHTTP2_TOKEN_LINK = 44,
|
||||
NGHTTP2_TOKEN_LOCATION = 45,
|
||||
NGHTTP2_TOKEN_MAX_FORWARDS = 46,
|
||||
NGHTTP2_TOKEN_PROXY_AUTHENTICATE = 47,
|
||||
NGHTTP2_TOKEN_PROXY_AUTHORIZATION = 48,
|
||||
NGHTTP2_TOKEN_RANGE = 49,
|
||||
NGHTTP2_TOKEN_REFERER = 50,
|
||||
NGHTTP2_TOKEN_REFRESH = 51,
|
||||
NGHTTP2_TOKEN_RETRY_AFTER = 52,
|
||||
NGHTTP2_TOKEN_SERVER = 53,
|
||||
NGHTTP2_TOKEN_SET_COOKIE = 54,
|
||||
NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY = 55,
|
||||
NGHTTP2_TOKEN_TRANSFER_ENCODING = 56,
|
||||
NGHTTP2_TOKEN_USER_AGENT = 57,
|
||||
NGHTTP2_TOKEN_VARY = 58,
|
||||
NGHTTP2_TOKEN_VIA = 59,
|
||||
NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,
|
||||
NGHTTP2_TOKEN_TE,
|
||||
NGHTTP2_TOKEN_CONNECTION,
|
||||
NGHTTP2_TOKEN_KEEP_ALIVE,
|
||||
NGHTTP2_TOKEN_PROXY_CONNECTION,
|
||||
NGHTTP2_TOKEN_UPGRADE
|
||||
} nghttp2_token;
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_HD_FLAG_NONE = 0,
|
||||
@@ -67,18 +128,14 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
nghttp2_nv nv;
|
||||
uint32_t name_hash;
|
||||
uint32_t value_hash;
|
||||
/* nghttp2_token value for nv.name. It could be -1 if we have no
|
||||
token for that header field name. */
|
||||
int token;
|
||||
/* Reference count */
|
||||
uint8_t ref;
|
||||
uint8_t flags;
|
||||
} nghttp2_hd_entry;
|
||||
|
||||
typedef struct {
|
||||
nghttp2_hd_entry ent;
|
||||
size_t index;
|
||||
} nghttp2_hd_static_entry;
|
||||
|
||||
typedef struct {
|
||||
nghttp2_hd_entry **buffer;
|
||||
size_t mask;
|
||||
@@ -107,6 +164,12 @@ typedef enum {
|
||||
NGHTTP2_HD_STATE_READ_VALUE
|
||||
} nghttp2_hd_inflate_state;
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_HD_WITH_INDEXING,
|
||||
NGHTTP2_HD_WITHOUT_INDEXING,
|
||||
NGHTTP2_HD_NEVER_INDEXING
|
||||
} nghttp2_hd_indexing_mode;
|
||||
|
||||
typedef struct {
|
||||
/* dynamic header table */
|
||||
nghttp2_hd_ringbuf hd_table;
|
||||
@@ -176,9 +239,8 @@ struct nghttp2_hd_inflater {
|
||||
* set in the |flags|, the content pointed by the |name| with length
|
||||
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
|
||||
* set in the |flags|, the content pointed by the |value| with length
|
||||
* |valuelen| is copied. The |name_hash| and |value_hash| are hash
|
||||
* value for |name| and |value| respectively. The hash function is
|
||||
* defined in nghttp2_hd.c.
|
||||
* |valuelen| is copied. The |token| is enum number looked up by
|
||||
* |name|. It could be -1 if we don't have that enum value.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -188,8 +250,7 @@ struct nghttp2_hd_inflater {
|
||||
*/
|
||||
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
|
||||
size_t namelen, uint8_t *value, size_t valuelen,
|
||||
uint32_t name_hash, uint32_t value_hash,
|
||||
nghttp2_mem *mem);
|
||||
int token, nghttp2_mem *mem);
|
||||
|
||||
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem);
|
||||
|
||||
@@ -271,13 +332,25 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
|
||||
*/
|
||||
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
|
||||
|
||||
/*
|
||||
* Similar to nghttp2_hd_inflate_hd(), but this takes additional
|
||||
* output parameter |token|. On successful header emission, it
|
||||
* contains nghttp2_token value for nv_out->name. It could be -1 if
|
||||
* we don't have enum value for the name. Other than that return
|
||||
* values and semantics are the same as nghttp2_hd_inflate_hd().
|
||||
*/
|
||||
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
int *token, uint8_t *in, size_t inlen,
|
||||
int in_final);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||
nghttp2_nv *nv, int inc_indexing);
|
||||
nghttp2_nv *nv, int indexing_mode);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
|
||||
int inc_indexing);
|
||||
int indexing_mode);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
|
||||
|
||||
@@ -168,10 +168,27 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
||||
ctx->accept = 1;
|
||||
}
|
||||
|
||||
/* Use macro to make the code simpler..., but error case is tricky.
|
||||
We spent most of the CPU in decoding, so we are doing this
|
||||
thing. */
|
||||
#define hd_huff_decode_sym_emit(bufs, sym, avail) \
|
||||
do { \
|
||||
if ((avail)) { \
|
||||
nghttp2_bufs_fast_addb((bufs), (sym)); \
|
||||
--(avail); \
|
||||
} else { \
|
||||
rv = nghttp2_bufs_addb((bufs), (sym)); \
|
||||
if (rv != 0) { \
|
||||
return rv; \
|
||||
} \
|
||||
(avail) = nghttp2_bufs_cur_avail((bufs)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_bufs *bufs, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
size_t i, j;
|
||||
size_t i;
|
||||
int rv;
|
||||
size_t avail;
|
||||
|
||||
@@ -180,30 +197,28 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
/* We use the decoding algorithm described in
|
||||
http://graphics.ics.uci.edu/pub/Prefix.pdf */
|
||||
for (i = 0; i < srclen; ++i) {
|
||||
uint8_t in = src[i] >> 4;
|
||||
for (j = 0; j < 2; ++j) {
|
||||
const nghttp2_huff_decode *t;
|
||||
const nghttp2_huff_decode *t;
|
||||
|
||||
t = &huff_decode_table[ctx->state][in];
|
||||
if (t->flags & NGHTTP2_HUFF_FAIL) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
if (avail) {
|
||||
nghttp2_bufs_fast_addb(bufs, t->sym);
|
||||
--avail;
|
||||
} else {
|
||||
rv = nghttp2_bufs_addb(bufs, t->sym);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
}
|
||||
ctx->state = t->state;
|
||||
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
|
||||
in = src[i] & 0xf;
|
||||
t = &huff_decode_table[ctx->state][src[i] >> 4];
|
||||
if (t->flags & NGHTTP2_HUFF_FAIL) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
/* this is macro, and may return from this function on error */
|
||||
hd_huff_decode_sym_emit(bufs, t->sym, avail);
|
||||
}
|
||||
|
||||
t = &huff_decode_table[t->state][src[i] & 0xf];
|
||||
if (t->flags & NGHTTP2_HUFF_FAIL) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
/* this is macro, and may return from this function on error */
|
||||
hd_huff_decode_sym_emit(bufs, t->sym, avail);
|
||||
}
|
||||
|
||||
ctx->state = t->state;
|
||||
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
|
||||
}
|
||||
if (final && !ctx->accept) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
|
||||
@@ -297,12 +297,18 @@ const char *nghttp2_strerror(int error_code) {
|
||||
return "The current session is closing";
|
||||
case NGHTTP2_ERR_HTTP_HEADER:
|
||||
return "Invalid HTTP header field was received";
|
||||
case NGHTTP2_ERR_HTTP_MESSAGING:
|
||||
return "Violation in HTTP messaging rule";
|
||||
case NGHTTP2_ERR_REFUSED_STREAM:
|
||||
return "Stream was refused";
|
||||
case NGHTTP2_ERR_INTERNAL:
|
||||
return "Internal error";
|
||||
case NGHTTP2_ERR_NOMEM:
|
||||
return "Out of memory";
|
||||
case NGHTTP2_ERR_CALLBACK_FAILURE:
|
||||
return "The user callback function failed";
|
||||
case NGHTTP2_ERR_BAD_PREFACE:
|
||||
return "Received bad connection preface";
|
||||
case NGHTTP2_ERR_BAD_CLIENT_MAGIC:
|
||||
return "Received bad clinet magic byte string";
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
||||
@@ -29,12 +29,16 @@
|
||||
#include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_mem.h"
|
||||
|
||||
#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
|
||||
|
||||
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
|
||||
|
||||
/*
|
||||
* Copies 2 byte unsigned integer |n| in host byte order to |buf| in
|
||||
* network byte order.
|
||||
|
||||
@@ -28,11 +28,8 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int memeq(const void *a, const void *b, size_t n) {
|
||||
return memcmp(a, b, n) == 0;
|
||||
}
|
||||
|
||||
#define streq(A, B, N) ((sizeof((A)) - 1) == (N) && memeq((A), (B), (N)))
|
||||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_helper.h"
|
||||
|
||||
static char downcase(char c) {
|
||||
return 'A' <= c && c <= 'Z' ? (c - 'A' + 'a') : c;
|
||||
@@ -50,129 +47,7 @@ static int memieq(const void *a, const void *b, size_t n) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define strieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_TOKEN__AUTHORITY,
|
||||
NGHTTP2_TOKEN__METHOD,
|
||||
NGHTTP2_TOKEN__PATH,
|
||||
NGHTTP2_TOKEN__SCHEME,
|
||||
NGHTTP2_TOKEN__STATUS,
|
||||
NGHTTP2_TOKEN_CONNECTION,
|
||||
NGHTTP2_TOKEN_CONTENT_LENGTH,
|
||||
NGHTTP2_TOKEN_HOST,
|
||||
NGHTTP2_TOKEN_KEEP_ALIVE,
|
||||
NGHTTP2_TOKEN_PROXY_CONNECTION,
|
||||
NGHTTP2_TOKEN_TE,
|
||||
NGHTTP2_TOKEN_TRANSFER_ENCODING,
|
||||
NGHTTP2_TOKEN_UPGRADE,
|
||||
NGHTTP2_TOKEN_MAXIDX,
|
||||
} nghttp2_token;
|
||||
|
||||
/*
|
||||
* This function was generated by genlibtokenlookup.py. Inspired by
|
||||
* h2o header lookup. https://github.com/h2o/h2o
|
||||
*/
|
||||
static int lookup_token(const uint8_t *name, size_t namelen) {
|
||||
switch (namelen) {
|
||||
case 2:
|
||||
switch (name[1]) {
|
||||
case 'e':
|
||||
if (streq("t", name, 1)) {
|
||||
return NGHTTP2_TOKEN_TE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
switch (name[3]) {
|
||||
case 't':
|
||||
if (streq("hos", name, 3)) {
|
||||
return NGHTTP2_TOKEN_HOST;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
switch (name[4]) {
|
||||
case 'h':
|
||||
if (streq(":pat", name, 4)) {
|
||||
return NGHTTP2_TOKEN__PATH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
switch (name[6]) {
|
||||
case 'd':
|
||||
if (streq(":metho", name, 6)) {
|
||||
return NGHTTP2_TOKEN__METHOD;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
if (streq(":schem", name, 6)) {
|
||||
return NGHTTP2_TOKEN__SCHEME;
|
||||
}
|
||||
if (streq("upgrad", name, 6)) {
|
||||
return NGHTTP2_TOKEN_UPGRADE;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (streq(":statu", name, 6)) {
|
||||
return NGHTTP2_TOKEN__STATUS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
switch (name[9]) {
|
||||
case 'e':
|
||||
if (streq("keep-aliv", name, 9)) {
|
||||
return NGHTTP2_TOKEN_KEEP_ALIVE;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
if (streq("connectio", name, 9)) {
|
||||
return NGHTTP2_TOKEN_CONNECTION;
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
if (streq(":authorit", name, 9)) {
|
||||
return NGHTTP2_TOKEN__AUTHORITY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
switch (name[13]) {
|
||||
case 'h':
|
||||
if (streq("content-lengt", name, 13)) {
|
||||
return NGHTTP2_TOKEN_CONTENT_LENGTH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
switch (name[15]) {
|
||||
case 'n':
|
||||
if (streq("proxy-connectio", name, 15)) {
|
||||
return NGHTTP2_TOKEN_PROXY_CONNECTION;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
switch (name[16]) {
|
||||
case 'g':
|
||||
if (streq("transfer-encodin", name, 16)) {
|
||||
return NGHTTP2_TOKEN_TRANSFER_ENCODING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
|
||||
|
||||
static int64_t parse_uint(const uint8_t *s, size_t len) {
|
||||
int64_t n = 0;
|
||||
@@ -238,9 +113,7 @@ static int check_path(nghttp2_stream *stream) {
|
||||
}
|
||||
|
||||
static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
int trailer) {
|
||||
int token;
|
||||
|
||||
int token, int trailer) {
|
||||
if (nv->name[0] == ':') {
|
||||
if (trailer ||
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
|
||||
@@ -248,8 +121,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
}
|
||||
|
||||
token = lookup_token(nv->name, nv->namelen);
|
||||
|
||||
switch (token) {
|
||||
case NGHTTP2_TOKEN__AUTHORITY:
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) {
|
||||
@@ -262,14 +133,14 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
switch (nv->valuelen) {
|
||||
case 4:
|
||||
if (streq("HEAD", nv->value, nv->valuelen)) {
|
||||
if (lstreq("HEAD", nv->value, nv->valuelen)) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
switch (nv->value[6]) {
|
||||
case 'T':
|
||||
if (streq("CONNECT", nv->value, nv->valuelen)) {
|
||||
if (lstreq("CONNECT", nv->value, nv->valuelen)) {
|
||||
if (stream->stream_id % 2 == 0) {
|
||||
/* we won't allow CONNECT for push */
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
@@ -282,7 +153,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
if (streq("OPTIONS", nv->value, nv->valuelen)) {
|
||||
if (lstreq("OPTIONS", nv->value, nv->valuelen)) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS;
|
||||
}
|
||||
break;
|
||||
@@ -338,7 +209,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
case NGHTTP2_TOKEN_UPGRADE:
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
case NGHTTP2_TOKEN_TE:
|
||||
if (!strieq("trailers", nv->value, nv->valuelen)) {
|
||||
if (!lstrieq("trailers", nv->value, nv->valuelen)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
break;
|
||||
@@ -356,9 +227,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
|
||||
static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
int trailer) {
|
||||
int token;
|
||||
|
||||
int token, int trailer) {
|
||||
if (nv->name[0] == ':') {
|
||||
if (trailer ||
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
|
||||
@@ -366,8 +235,6 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
}
|
||||
|
||||
token = lookup_token(nv->name, nv->namelen);
|
||||
|
||||
switch (token) {
|
||||
case NGHTTP2_TOKEN__STATUS: {
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) {
|
||||
@@ -400,7 +267,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
case NGHTTP2_TOKEN_UPGRADE:
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
case NGHTTP2_TOKEN_TE:
|
||||
if (!strieq("trailers", nv->value, nv->valuelen)) {
|
||||
if (!lstrieq("trailers", nv->value, nv->valuelen)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
break;
|
||||
@@ -418,7 +285,8 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
|
||||
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
nghttp2_frame *frame, nghttp2_nv *nv, int trailer) {
|
||||
nghttp2_frame *frame, nghttp2_nv *nv, int token,
|
||||
int trailer) {
|
||||
/* We are strict for pseudo header field. One bad character should
|
||||
lead to fail. OTOH, we should be a bit forgiving for regular
|
||||
headers, since existing public internet has so much illegal
|
||||
@@ -458,10 +326,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
}
|
||||
|
||||
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
return http_request_on_header(stream, nv, trailer);
|
||||
return http_request_on_header(stream, nv, token, trailer);
|
||||
}
|
||||
|
||||
return http_response_on_header(stream, nv, trailer);
|
||||
return http_response_on_header(stream, nv, token, trailer);
|
||||
}
|
||||
|
||||
int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
||||
@@ -574,14 +442,15 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream,
|
||||
/* TODO we should do this strictly. */
|
||||
for (i = 0; i < nvlen; ++i) {
|
||||
const nghttp2_nv *nv = &nva[i];
|
||||
if (lookup_token(nv->name, nv->namelen) != NGHTTP2_TOKEN__METHOD) {
|
||||
if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
|
||||
memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
|
||||
continue;
|
||||
}
|
||||
if (streq("CONNECT", nv->value, nv->valuelen)) {
|
||||
if (lstreq("CONNECT", nv->value, nv->valuelen)) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
|
||||
return;
|
||||
}
|
||||
if (streq("HEAD", nv->value, nv->valuelen)) {
|
||||
if (lstreq("HEAD", nv->value, nv->valuelen)) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
/*
|
||||
* This function is called when HTTP header field |nv| in |frame| is
|
||||
* received for |stream|. This function will validate |nv| against
|
||||
* the current state of stream.
|
||||
* the current state of stream. The |token| is nghttp2_token value
|
||||
* for nv->name, or -1 if we don't have enum value for the name.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -48,7 +49,8 @@
|
||||
* if it was not received because of compatibility reasons.
|
||||
*/
|
||||
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
nghttp2_frame *frame, nghttp2_nv *nv, int trailer);
|
||||
nghttp2_frame *frame, nghttp2_nv *nv, int token,
|
||||
int trailer);
|
||||
|
||||
/*
|
||||
* This function is called when request header is received. This
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
typedef int (*nghttp2_compar)(const void *lhs, const void *rhs);
|
||||
/* "less" function, return nonzero if |lhs| is less than |rhs|. */
|
||||
typedef int (*nghttp2_less)(const void *lhs, const void *rhs);
|
||||
|
||||
/* Internal error code. They must be in the range [-499, -100],
|
||||
inclusive. */
|
||||
@@ -51,7 +52,7 @@ typedef enum {
|
||||
* Invalid HTTP header field was received but it can be treated as
|
||||
* if it was not received because of compatibility reasons.
|
||||
*/
|
||||
NGHTTP2_ERR_IGN_HTTP_HEADER = -105,
|
||||
NGHTTP2_ERR_IGN_HTTP_HEADER = -105
|
||||
} nghttp2_internal_error;
|
||||
|
||||
#endif /* NGHTTP2_INT_H */
|
||||
|
||||
@@ -37,8 +37,55 @@
|
||||
#include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif /* HAVE_WINSOCK2_H */
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
/* Windows requires ws2_32 library for ntonl family functions. We
|
||||
define inline functions for those function so that we don't have
|
||||
dependeny on that lib. */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STIN static __inline
|
||||
#else
|
||||
#define STIN static inline
|
||||
#endif
|
||||
|
||||
STIN uint32_t htonl(uint32_t hostlong) {
|
||||
uint32_t res;
|
||||
unsigned char *p = (unsigned char *)&res;
|
||||
*p++ = hostlong >> 24;
|
||||
*p++ = (hostlong >> 16) & 0xffu;
|
||||
*p++ = (hostlong >> 8) & 0xffu;
|
||||
*p = hostlong & 0xffu;
|
||||
return res;
|
||||
}
|
||||
|
||||
STIN uint16_t htons(uint16_t hostshort) {
|
||||
uint16_t res;
|
||||
unsigned char *p = (unsigned char *)&res;
|
||||
*p++ = hostshort >> 8;
|
||||
*p = hostshort & 0xffu;
|
||||
return res;
|
||||
}
|
||||
|
||||
STIN uint32_t ntohl(uint32_t netlong) {
|
||||
uint32_t res;
|
||||
unsigned char *p = (unsigned char *)&netlong;
|
||||
res = *p++ << 24;
|
||||
res += *p++ << 16;
|
||||
res += *p++ << 8;
|
||||
res += *p;
|
||||
return res;
|
||||
}
|
||||
|
||||
STIN uint16_t ntohs(uint16_t netshort) {
|
||||
uint16_t res;
|
||||
unsigned char *p = (unsigned char *)&netshort;
|
||||
res = *p++ << 8;
|
||||
res += *p;
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
#endif /* NGHTTP2_NET_H */
|
||||
|
||||
@@ -47,9 +47,9 @@ void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
|
||||
option->peer_max_concurrent_streams = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_RECV_CLIENT_PREFACE;
|
||||
option->recv_client_preface = val;
|
||||
void nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC;
|
||||
option->no_recv_client_magic = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) {
|
||||
|
||||
@@ -57,8 +57,8 @@ typedef enum {
|
||||
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
|
||||
*/
|
||||
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1,
|
||||
NGHTTP2_OPT_RECV_CLIENT_PREFACE = 1 << 2,
|
||||
NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3,
|
||||
NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2,
|
||||
NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
@@ -79,9 +79,9 @@ struct nghttp2_option {
|
||||
*/
|
||||
uint8_t no_auto_window_update;
|
||||
/**
|
||||
* NGHTTP2_OPT_RECV_CLIENT_PREFACE
|
||||
* NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC
|
||||
*/
|
||||
uint8_t recv_client_preface;
|
||||
uint8_t no_recv_client_magic;
|
||||
/**
|
||||
* NGHTTP2_OPT_NO_HTTP_MESSAGING
|
||||
*/
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
#include "nghttp2_outbound_item.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
|
||||
item->cycle = 0;
|
||||
item->qnext = NULL;
|
||||
item->queued = 0;
|
||||
|
||||
memset(&item->aux_data, 0, sizeof(nghttp2_aux_data));
|
||||
}
|
||||
|
||||
void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
|
||||
nghttp2_frame *frame;
|
||||
@@ -65,3 +74,32 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q) {
|
||||
q->head = q->tail = NULL;
|
||||
q->n = 0;
|
||||
}
|
||||
|
||||
void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
|
||||
nghttp2_outbound_item *item) {
|
||||
if (q->tail) {
|
||||
q->tail = q->tail->qnext = item;
|
||||
} else {
|
||||
q->head = q->tail = item;
|
||||
}
|
||||
++q->n;
|
||||
}
|
||||
|
||||
void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q) {
|
||||
nghttp2_outbound_item *item;
|
||||
if (!q->head) {
|
||||
return;
|
||||
}
|
||||
item = q->head;
|
||||
q->head = q->head->qnext;
|
||||
item->qnext = NULL;
|
||||
if (!q->head) {
|
||||
q->tail = NULL;
|
||||
}
|
||||
--q->n;
|
||||
}
|
||||
|
||||
@@ -33,13 +33,6 @@
|
||||
#include "nghttp2_frame.h"
|
||||
#include "nghttp2_mem.h"
|
||||
|
||||
/* A bit higher weight for non-DATA frames */
|
||||
#define NGHTTP2_OB_EX_WEIGHT 300
|
||||
/* Higher weight for SETTINGS */
|
||||
#define NGHTTP2_OB_SETTINGS_WEIGHT 301
|
||||
/* Highest weight for PING */
|
||||
#define NGHTTP2_OB_PING_WEIGHT 302
|
||||
|
||||
/* struct used for HEADERS and PUSH_PROMISE frame */
|
||||
typedef struct {
|
||||
nghttp2_data_provider data_prd;
|
||||
@@ -74,6 +67,10 @@ typedef struct {
|
||||
* |eof| is 0. It becomes 1 after all data were read.
|
||||
*/
|
||||
uint8_t eof;
|
||||
/**
|
||||
* The flag to indicate that NGHTTP2_DATA_FLAG_NO_COPY is used.
|
||||
*/
|
||||
uint8_t no_copy;
|
||||
} nghttp2_data_aux_data;
|
||||
|
||||
typedef enum {
|
||||
@@ -84,7 +81,7 @@ typedef enum {
|
||||
/* indicates that this GOAWAY is just a notification for graceful
|
||||
shutdown. No nghttp2_session.goaway_flags should be updated on
|
||||
the reaction to this frame. */
|
||||
NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE = 0x2,
|
||||
NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE = 0x2
|
||||
} nghttp2_goaway_aux_flag;
|
||||
|
||||
/* struct used for GOAWAY frame */
|
||||
@@ -100,19 +97,31 @@ typedef union {
|
||||
nghttp2_goaway_aux_data goaway;
|
||||
} nghttp2_aux_data;
|
||||
|
||||
typedef struct {
|
||||
struct nghttp2_outbound_item;
|
||||
typedef struct nghttp2_outbound_item nghttp2_outbound_item;
|
||||
|
||||
struct nghttp2_outbound_item {
|
||||
nghttp2_frame frame;
|
||||
nghttp2_aux_data aux_data;
|
||||
int64_t seq;
|
||||
/* Reset count of weight. See comment for last_cycle in
|
||||
nghttp2_session.h */
|
||||
/* The priority used in priority comparion. Smaller is served
|
||||
ealier. For PING, SETTINGS and non-DATA frames (excluding
|
||||
response HEADERS frame) have dedicated cycle value defined above.
|
||||
For DATA frame, cycle is computed by taking into account of
|
||||
effective weight and frame payload length previously sent, so
|
||||
that the amount of transmission is distributed across streams
|
||||
proportional to effective weight (inside a tree). */
|
||||
uint64_t cycle;
|
||||
/* The priority used in priority comparion. Larger is served
|
||||
ealier. */
|
||||
int32_t weight;
|
||||
nghttp2_outbound_item *qnext;
|
||||
/* nonzero if this object is queued. */
|
||||
uint8_t queued;
|
||||
} nghttp2_outbound_item;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initializes |item|. No memory allocation is done in this function.
|
||||
* Don't call nghttp2_outbound_item_free() until frame member is
|
||||
* initialized.
|
||||
*/
|
||||
void nghttp2_outbound_item_init(nghttp2_outbound_item *item);
|
||||
|
||||
/*
|
||||
* Deallocates resource for |item|. If |item| is NULL, this function
|
||||
@@ -120,4 +129,29 @@ typedef struct {
|
||||
*/
|
||||
void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* queue for nghttp2_outbound_item.
|
||||
*/
|
||||
typedef struct {
|
||||
nghttp2_outbound_item *head, *tail;
|
||||
/* number of items in this queue. */
|
||||
size_t n;
|
||||
} nghttp2_outbound_queue;
|
||||
|
||||
void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q);
|
||||
|
||||
/* Pushes |item| into |q| */
|
||||
void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
|
||||
nghttp2_outbound_item *item);
|
||||
|
||||
/* Pops |item| at the top from |q|. If |q| is empty, nothing
|
||||
happens. */
|
||||
void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q);
|
||||
|
||||
/* Returns the top item. */
|
||||
#define nghttp2_outbound_queue_top(Q) ((Q)->head)
|
||||
|
||||
/* Returns the size of the queue */
|
||||
#define nghttp2_outbound_queue_size(Q) ((Q)->n)
|
||||
|
||||
#endif /* NGHTTP2_OUTBOUND_ITEM_H */
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
#include "nghttp2_pq.h"
|
||||
|
||||
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar, nghttp2_mem *mem) {
|
||||
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) {
|
||||
pq->mem = mem;
|
||||
pq->capacity = 128;
|
||||
pq->q = nghttp2_mem_malloc(mem, pq->capacity * sizeof(void *));
|
||||
@@ -32,7 +32,7 @@ int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar, nghttp2_mem *mem) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
pq->length = 0;
|
||||
pq->compar = compar;
|
||||
pq->less = less;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ static void bubble_up(nghttp2_pq *pq, size_t index) {
|
||||
return;
|
||||
} else {
|
||||
size_t parent = (index - 1) / 2;
|
||||
if (pq->compar(pq->q[parent], pq->q[index]) > 0) {
|
||||
if (pq->less(pq->q[index], pq->q[parent])) {
|
||||
swap(pq, parent, index);
|
||||
bubble_up(pq, parent);
|
||||
}
|
||||
@@ -93,7 +93,7 @@ static void bubble_down(nghttp2_pq *pq, size_t index) {
|
||||
if (j >= pq->length) {
|
||||
break;
|
||||
}
|
||||
if (pq->compar(pq->q[minindex], pq->q[j]) > 0) {
|
||||
if (pq->less(pq->q[j], pq->q[minindex])) {
|
||||
minindex = j;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ typedef struct {
|
||||
/* The maximum number of items this pq can store. This is
|
||||
automatically extended when length is reached to this value. */
|
||||
size_t capacity;
|
||||
/* The compare function between items */
|
||||
nghttp2_compar compar;
|
||||
/* The less function between items */
|
||||
nghttp2_less less;
|
||||
} nghttp2_pq;
|
||||
|
||||
/*
|
||||
@@ -58,7 +58,7 @@ typedef struct {
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar cmp, nghttp2_mem *mem);
|
||||
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* Deallocates any resources allocated for |pq|. The stored items are
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,13 +46,15 @@
|
||||
*/
|
||||
typedef enum {
|
||||
NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0,
|
||||
NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE = 1 << 1,
|
||||
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
|
||||
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
|
||||
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2
|
||||
} nghttp2_optmask;
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_OB_POP_ITEM,
|
||||
NGHTTP2_OB_SEND_DATA
|
||||
NGHTTP2_OB_SEND_DATA,
|
||||
NGHTTP2_OB_SEND_NO_COPY,
|
||||
NGHTTP2_OB_SEND_CLIENT_MAGIC
|
||||
} nghttp2_outbound_state;
|
||||
|
||||
typedef struct {
|
||||
@@ -68,7 +70,7 @@ typedef struct {
|
||||
/* Internal state when receiving incoming frame */
|
||||
typedef enum {
|
||||
/* Receiving frame header */
|
||||
NGHTTP2_IB_READ_CLIENT_PREFACE,
|
||||
NGHTTP2_IB_READ_CLIENT_MAGIC,
|
||||
NGHTTP2_IB_READ_FIRST_SETTINGS,
|
||||
NGHTTP2_IB_READ_HEAD,
|
||||
NGHTTP2_IB_READ_NBYTE,
|
||||
@@ -83,7 +85,7 @@ typedef enum {
|
||||
NGHTTP2_IB_READ_PAD_DATA,
|
||||
NGHTTP2_IB_READ_DATA,
|
||||
NGHTTP2_IB_IGN_DATA,
|
||||
NGHTTP2_IB_IGN_ALL,
|
||||
NGHTTP2_IB_IGN_ALL
|
||||
} nghttp2_inbound_state;
|
||||
|
||||
#define NGHTTP2_INBOUND_NUM_IV 7
|
||||
@@ -135,18 +137,21 @@ typedef enum {
|
||||
/* Flag means GOAWAY was sent */
|
||||
NGHTTP2_GOAWAY_SENT = 0x4,
|
||||
/* Flag means GOAWAY was received */
|
||||
NGHTTP2_GOAWAY_RECV = 0x8,
|
||||
NGHTTP2_GOAWAY_RECV = 0x8
|
||||
} nghttp2_goaway_flag;
|
||||
|
||||
struct nghttp2_session {
|
||||
nghttp2_map /* <nghttp2_stream*> */ streams;
|
||||
nghttp2_stream_roots roots;
|
||||
/* Queue for outbound frames other than stream-creating HEADERS and
|
||||
DATA */
|
||||
nghttp2_pq /* <nghttp2_outbound_item*> */ ob_pq;
|
||||
/* Queue for outbound stream-creating HEADERS frame */
|
||||
nghttp2_pq /* <nghttp2_outbound_item*> */ ob_ss_pq;
|
||||
/* QUeue for DATA frame */
|
||||
/* Queue for outbound urgent frames (PING and SETTINGS) */
|
||||
nghttp2_outbound_queue ob_urgent;
|
||||
/* Queue for non-DATA frames */
|
||||
nghttp2_outbound_queue ob_reg;
|
||||
/* Queue for outbound stream-creating HEADERS (request or push
|
||||
response) frame, which are subject to
|
||||
SETTINGS_MAX_CONCURRENT_STREAMS limit. */
|
||||
nghttp2_outbound_queue ob_syn;
|
||||
/* Queue for DATA frame */
|
||||
nghttp2_pq /* <nghttp2_outbound_item*> */ ob_da_pq;
|
||||
nghttp2_active_outbound_item aob;
|
||||
nghttp2_inbound_frame iframe;
|
||||
@@ -155,22 +160,8 @@ struct nghttp2_session {
|
||||
nghttp2_session_callbacks callbacks;
|
||||
/* Memory allocator */
|
||||
nghttp2_mem mem;
|
||||
/* Sequence number of outbound frame to maintain the order of
|
||||
enqueue if priority is equal. */
|
||||
int64_t next_seq;
|
||||
/* Reset count of nghttp2_outbound_item's weight. We decrements
|
||||
weight each time DATA is sent to simulate resource sharing. We
|
||||
use priority queue and larger weight has the precedence. If
|
||||
weight is reached to lowest weight, it resets to its initial
|
||||
weight. If this happens, other items which have the lower weight
|
||||
currently but same initial weight cannot send DATA until item
|
||||
having large weight is decreased. To avoid this, we use this
|
||||
cycle variable. Initally, this is set to 1. If weight gets
|
||||
lowest weight, and if item's cycle == last_cycle, we increments
|
||||
last_cycle and assigns it to item's cycle. Otherwise, just
|
||||
assign last_cycle. In priority queue comparator, we first
|
||||
compare items' cycle value. Lower cycle value has the
|
||||
precedence. */
|
||||
/* Base value when we schedule next DATA frame write. This is
|
||||
updated when one frame was written. */
|
||||
uint64_t last_cycle;
|
||||
void *user_data;
|
||||
/* Points to the latest closed stream. NULL if there is no closed
|
||||
@@ -290,14 +281,6 @@ typedef struct {
|
||||
int nghttp2_session_is_my_stream_id(nghttp2_session *session,
|
||||
int32_t stream_id);
|
||||
|
||||
/*
|
||||
* Initializes |item|. No memory allocation is done in this function.
|
||||
* Don't call nghttp2_outbound_item_free() until frame member is
|
||||
* initialized.
|
||||
*/
|
||||
void nghttp2_session_outbound_item_init(nghttp2_session *session,
|
||||
nghttp2_outbound_item *item);
|
||||
|
||||
/*
|
||||
* Adds |item| to the outbound queue in |session|. When this function
|
||||
* succeeds, it takes ownership of |item|. So caller must not free it
|
||||
@@ -703,13 +686,8 @@ nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session,
|
||||
*/
|
||||
int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
size_t datamax, nghttp2_frame *frame,
|
||||
nghttp2_data_aux_data *aux_data);
|
||||
|
||||
/*
|
||||
* Returns top of outbound frame queue. This function returns NULL if
|
||||
* queue is empty.
|
||||
*/
|
||||
nghttp2_outbound_item *nghttp2_session_get_ob_pq_top(nghttp2_session *session);
|
||||
nghttp2_data_aux_data *aux_data,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Pops and returns next item to send. If there is no such item,
|
||||
|
||||
@@ -63,7 +63,6 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
stream->effective_weight = stream->weight;
|
||||
stream->sum_dep_weight = 0;
|
||||
stream->sum_norest_weight = 0;
|
||||
stream->sum_top_weight = 0;
|
||||
|
||||
stream->roots = roots;
|
||||
stream->root_prev = NULL;
|
||||
@@ -87,7 +86,8 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
|
||||
}
|
||||
|
||||
static int stream_push_item(nghttp2_stream *stream, nghttp2_session *session) {
|
||||
int rv;
|
||||
/* This is required for Android NDK r10d */
|
||||
int rv = 0;
|
||||
nghttp2_outbound_item *item;
|
||||
|
||||
assert(stream->item);
|
||||
@@ -101,33 +101,33 @@ static int stream_push_item(nghttp2_stream *stream, nghttp2_session *session) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (item->weight > stream->effective_weight) {
|
||||
item->weight = stream->effective_weight;
|
||||
}
|
||||
|
||||
item->cycle = session->last_cycle;
|
||||
|
||||
switch (item->frame.hd.type) {
|
||||
case NGHTTP2_DATA:
|
||||
/* Penalize item by delaying scheduling according to effective
|
||||
weight. This will delay low priority stream, which is good.
|
||||
OTOH, this may incur delay for high priority item. Will
|
||||
see. */
|
||||
item->cycle =
|
||||
session->last_cycle +
|
||||
NGHTTP2_DATA_PAYLOADLEN * NGHTTP2_MAX_WEIGHT / stream->effective_weight;
|
||||
|
||||
rv = nghttp2_pq_push(&session->ob_da_pq, item);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_HEADERS:
|
||||
if (stream->state == NGHTTP2_STREAM_RESERVED) {
|
||||
rv = nghttp2_pq_push(&session->ob_ss_pq, item);
|
||||
nghttp2_outbound_queue_push(&session->ob_syn, item);
|
||||
} else {
|
||||
rv = nghttp2_pq_push(&session->ob_pq, item);
|
||||
nghttp2_outbound_queue_push(&session->ob_reg, item);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rv = 0;
|
||||
/* should not reach here */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
item->queued = 1;
|
||||
|
||||
return 0;
|
||||
@@ -178,18 +178,6 @@ int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
stream_dep_distributed_top_effective_weight(nghttp2_stream *stream,
|
||||
int32_t weight) {
|
||||
if (stream->sum_top_weight == 0) {
|
||||
return stream->effective_weight;
|
||||
}
|
||||
|
||||
weight = stream->effective_weight * weight / stream->sum_top_weight;
|
||||
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
static void stream_update_dep_set_rest(nghttp2_stream *stream);
|
||||
|
||||
/* Updates effective_weight of descendant streams in subtree of
|
||||
@@ -199,10 +187,9 @@ static void stream_update_dep_effective_weight(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: update_dep_effective_weight "
|
||||
"stream(%p)=%d, weight=%d, sum_norest_weight=%d, "
|
||||
"sum_top_weight=%d\n",
|
||||
"stream(%p)=%d, weight=%d, sum_norest_weight=%d\n",
|
||||
stream, stream->stream_id, stream->weight,
|
||||
stream->sum_norest_weight, stream->sum_top_weight));
|
||||
stream->sum_norest_weight));
|
||||
|
||||
/* stream->sum_norest_weight == 0 means there is no
|
||||
NGHTTP2_STREAM_DPRI_TOP under stream */
|
||||
@@ -211,47 +198,13 @@ static void stream_update_dep_effective_weight(nghttp2_stream *stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is no direct descendant whose dpri is
|
||||
NGHTTP2_STREAM_DPRI_TOP, indirect descendants have the chance to
|
||||
send data, so recursively set weight for descendants. */
|
||||
if (stream->sum_top_weight == 0) {
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->dpri != NGHTTP2_STREAM_DPRI_REST) {
|
||||
si->effective_weight =
|
||||
nghttp2_stream_dep_distributed_effective_weight(stream, si->weight);
|
||||
}
|
||||
|
||||
stream_update_dep_effective_weight(si);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is at least one direct descendant whose dpri is
|
||||
NGHTTP2_STREAM_DPRI_TOP, we won't give a chance to indirect
|
||||
descendants, since closed or blocked stream's weight is
|
||||
distributed among its siblings */
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
if (si->dpri != NGHTTP2_STREAM_DPRI_REST) {
|
||||
si->effective_weight =
|
||||
stream_dep_distributed_top_effective_weight(stream, si->weight);
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: stream=%d top eweight=%d\n",
|
||||
si->stream_id, si->effective_weight));
|
||||
|
||||
continue;
|
||||
nghttp2_stream_dep_distributed_effective_weight(stream, si->weight);
|
||||
}
|
||||
|
||||
if (si->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM) {
|
||||
DEBUGF(fprintf(stderr, "stream: stream=%d no_item, ignored\n",
|
||||
si->stream_id));
|
||||
|
||||
/* Since we marked NGHTTP2_STREAM_DPRI_TOP under si, we make
|
||||
them NGHTTP2_STREAM_DPRI_REST again. */
|
||||
stream_update_dep_set_rest(si->dep_next);
|
||||
} else {
|
||||
DEBUGF(
|
||||
fprintf(stderr, "stream: stream=%d rest, ignored\n", si->stream_id));
|
||||
}
|
||||
stream_update_dep_effective_weight(si);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,25 +300,20 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream,
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates stream->sum_norest_weight and stream->sum_top_weight
|
||||
* recursively. We have to gather effective sum of weight of
|
||||
* descendants. If stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM, we
|
||||
* have to go deeper and check that any of its descendants has dpri
|
||||
* value of NGHTTP2_STREAM_DPRI_TOP. If so, we have to add weight of
|
||||
* its direct descendants to stream->sum_norest_weight. To make this
|
||||
* work, this function returns 1 if any of its descendants has dpri
|
||||
* value of NGHTTP2_STREAM_DPRI_TOP, otherwise 0.
|
||||
*
|
||||
* Calculating stream->sum_top-weight is very simple compared to
|
||||
* stream->sum_norest_weight. It just adds up the weight of direct
|
||||
* descendants whose dpri is NGHTTP2_STREAM_DPRI_TOP.
|
||||
* Updates stream->sum_norest_weight recursively. We have to gather
|
||||
* effective sum of weight of descendants. If stream->dpri ==
|
||||
* NGHTTP2_STREAM_DPRI_NO_ITEM, we have to go deeper and check that
|
||||
* any of its descendants has dpri value of NGHTTP2_STREAM_DPRI_TOP.
|
||||
* If so, we have to add weight of its direct descendants to
|
||||
* stream->sum_norest_weight. To make this work, this function
|
||||
* returns 1 if any of its descendants has dpri value of
|
||||
* NGHTTP2_STREAM_DPRI_TOP, otherwise 0.
|
||||
*/
|
||||
static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int rv;
|
||||
|
||||
stream->sum_norest_weight = 0;
|
||||
stream->sum_top_weight = 0;
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
return 1;
|
||||
@@ -383,10 +331,6 @@ static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) {
|
||||
rv = 1;
|
||||
stream->sum_norest_weight += si->weight;
|
||||
}
|
||||
|
||||
if (si->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
stream->sum_top_weight += si->weight;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
@@ -133,7 +133,7 @@ typedef enum {
|
||||
/* "http" or "https" scheme */
|
||||
NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 12,
|
||||
/* set if final response is expected */
|
||||
NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 13,
|
||||
NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 13
|
||||
} nghttp2_http_flag;
|
||||
|
||||
typedef enum {
|
||||
@@ -154,6 +154,10 @@ typedef struct nghttp2_stream nghttp2_stream;
|
||||
struct nghttp2_stream {
|
||||
/* Intrusive Map */
|
||||
nghttp2_map_entry map_entry;
|
||||
/* Content-Length of request/response body. -1 if unknown. */
|
||||
int64_t content_length;
|
||||
/* Received body so far */
|
||||
int64_t recv_content_length;
|
||||
/* pointers to form dependency tree. If multiple streams depend on
|
||||
a stream, only one stream (left most) has non-NULL dep_prev which
|
||||
points to the stream it depends on. The remaining streams are
|
||||
@@ -213,22 +217,15 @@ struct nghttp2_stream {
|
||||
descendant with dpri == NGHTTP2_STREAM_DPRI_TOP. We use this
|
||||
value to calculate effective weight. */
|
||||
int32_t sum_norest_weight;
|
||||
/* sum of weight of direct descendants whose dpri value is
|
||||
NGHTTP2_STREAM_DPRI_TOP */
|
||||
int32_t sum_top_weight;
|
||||
nghttp2_stream_state state;
|
||||
/* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
|
||||
uint8_t flags;
|
||||
/* Bitwise OR of zero or more nghttp2_shut_flag values */
|
||||
uint8_t shut_flags;
|
||||
/* Content-Length of request/response body. -1 if unknown. */
|
||||
int64_t content_length;
|
||||
/* Received body so far */
|
||||
int64_t recv_content_length;
|
||||
/* status code from remote server */
|
||||
int16_t status_code;
|
||||
/* Bitwise OR of zero or more nghttp2_http_flag values */
|
||||
uint16_t http_flags;
|
||||
/* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
|
||||
uint8_t flags;
|
||||
/* Bitwise OR of zero or more nghttp2_shut_flag values */
|
||||
uint8_t shut_flags;
|
||||
};
|
||||
|
||||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
|
||||
@@ -62,7 +62,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nghttp2_session_outbound_item_init(session, item);
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
if (data_prd != NULL && data_prd->read_callback != NULL) {
|
||||
item->aux_data.headers.data_prd = *data_prd;
|
||||
@@ -212,7 +212,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_session_outbound_item_init(session, item);
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
frame = &item->frame;
|
||||
|
||||
@@ -299,7 +299,7 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_session_outbound_item_init(session, item);
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
item->aux_data.headers.stream_user_data = promised_stream_user_data;
|
||||
|
||||
@@ -376,15 +376,6 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_submit_altsvc(nghttp2_session *session _U_, uint8_t flags _U_,
|
||||
int32_t stream_id _U_, uint32_t max_age _U_,
|
||||
uint16_t port _U_, const uint8_t *protocol_id _U_,
|
||||
size_t protocol_id_len _U_, const uint8_t *host _U_,
|
||||
size_t host_len _U_, const uint8_t *origin _U_,
|
||||
size_t origin_len _U_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||
@@ -453,7 +444,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_session_outbound_item_init(session, item);
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
frame = &item->frame;
|
||||
aux_data = &item->aux_data.data;
|
||||
|
||||
432
mkhufftbl.py
432
mkhufftbl.py
@@ -10,8 +10,271 @@
|
||||
from __future__ import unicode_literals
|
||||
import re
|
||||
import sys
|
||||
import StringIO
|
||||
|
||||
# From [1]
|
||||
HUFFMAN_CODE_TABLE = """\
|
||||
( 0) |11111111|11000 1ff8 [13]
|
||||
( 1) |11111111|11111111|1011000 7fffd8 [23]
|
||||
( 2) |11111111|11111111|11111110|0010 fffffe2 [28]
|
||||
( 3) |11111111|11111111|11111110|0011 fffffe3 [28]
|
||||
( 4) |11111111|11111111|11111110|0100 fffffe4 [28]
|
||||
( 5) |11111111|11111111|11111110|0101 fffffe5 [28]
|
||||
( 6) |11111111|11111111|11111110|0110 fffffe6 [28]
|
||||
( 7) |11111111|11111111|11111110|0111 fffffe7 [28]
|
||||
( 8) |11111111|11111111|11111110|1000 fffffe8 [28]
|
||||
( 9) |11111111|11111111|11101010 ffffea [24]
|
||||
( 10) |11111111|11111111|11111111|111100 3ffffffc [30]
|
||||
( 11) |11111111|11111111|11111110|1001 fffffe9 [28]
|
||||
( 12) |11111111|11111111|11111110|1010 fffffea [28]
|
||||
( 13) |11111111|11111111|11111111|111101 3ffffffd [30]
|
||||
( 14) |11111111|11111111|11111110|1011 fffffeb [28]
|
||||
( 15) |11111111|11111111|11111110|1100 fffffec [28]
|
||||
( 16) |11111111|11111111|11111110|1101 fffffed [28]
|
||||
( 17) |11111111|11111111|11111110|1110 fffffee [28]
|
||||
( 18) |11111111|11111111|11111110|1111 fffffef [28]
|
||||
( 19) |11111111|11111111|11111111|0000 ffffff0 [28]
|
||||
( 20) |11111111|11111111|11111111|0001 ffffff1 [28]
|
||||
( 21) |11111111|11111111|11111111|0010 ffffff2 [28]
|
||||
( 22) |11111111|11111111|11111111|111110 3ffffffe [30]
|
||||
( 23) |11111111|11111111|11111111|0011 ffffff3 [28]
|
||||
( 24) |11111111|11111111|11111111|0100 ffffff4 [28]
|
||||
( 25) |11111111|11111111|11111111|0101 ffffff5 [28]
|
||||
( 26) |11111111|11111111|11111111|0110 ffffff6 [28]
|
||||
( 27) |11111111|11111111|11111111|0111 ffffff7 [28]
|
||||
( 28) |11111111|11111111|11111111|1000 ffffff8 [28]
|
||||
( 29) |11111111|11111111|11111111|1001 ffffff9 [28]
|
||||
( 30) |11111111|11111111|11111111|1010 ffffffa [28]
|
||||
( 31) |11111111|11111111|11111111|1011 ffffffb [28]
|
||||
' ' ( 32) |010100 14 [ 6]
|
||||
'!' ( 33) |11111110|00 3f8 [10]
|
||||
'"' ( 34) |11111110|01 3f9 [10]
|
||||
'#' ( 35) |11111111|1010 ffa [12]
|
||||
'$' ( 36) |11111111|11001 1ff9 [13]
|
||||
'%' ( 37) |010101 15 [ 6]
|
||||
'&' ( 38) |11111000 f8 [ 8]
|
||||
''' ( 39) |11111111|010 7fa [11]
|
||||
'(' ( 40) |11111110|10 3fa [10]
|
||||
')' ( 41) |11111110|11 3fb [10]
|
||||
'*' ( 42) |11111001 f9 [ 8]
|
||||
'+' ( 43) |11111111|011 7fb [11]
|
||||
',' ( 44) |11111010 fa [ 8]
|
||||
'-' ( 45) |010110 16 [ 6]
|
||||
'.' ( 46) |010111 17 [ 6]
|
||||
'/' ( 47) |011000 18 [ 6]
|
||||
'0' ( 48) |00000 0 [ 5]
|
||||
'1' ( 49) |00001 1 [ 5]
|
||||
'2' ( 50) |00010 2 [ 5]
|
||||
'3' ( 51) |011001 19 [ 6]
|
||||
'4' ( 52) |011010 1a [ 6]
|
||||
'5' ( 53) |011011 1b [ 6]
|
||||
'6' ( 54) |011100 1c [ 6]
|
||||
'7' ( 55) |011101 1d [ 6]
|
||||
'8' ( 56) |011110 1e [ 6]
|
||||
'9' ( 57) |011111 1f [ 6]
|
||||
':' ( 58) |1011100 5c [ 7]
|
||||
';' ( 59) |11111011 fb [ 8]
|
||||
'<' ( 60) |11111111|1111100 7ffc [15]
|
||||
'=' ( 61) |100000 20 [ 6]
|
||||
'>' ( 62) |11111111|1011 ffb [12]
|
||||
'?' ( 63) |11111111|00 3fc [10]
|
||||
'@' ( 64) |11111111|11010 1ffa [13]
|
||||
'A' ( 65) |100001 21 [ 6]
|
||||
'B' ( 66) |1011101 5d [ 7]
|
||||
'C' ( 67) |1011110 5e [ 7]
|
||||
'D' ( 68) |1011111 5f [ 7]
|
||||
'E' ( 69) |1100000 60 [ 7]
|
||||
'F' ( 70) |1100001 61 [ 7]
|
||||
'G' ( 71) |1100010 62 [ 7]
|
||||
'H' ( 72) |1100011 63 [ 7]
|
||||
'I' ( 73) |1100100 64 [ 7]
|
||||
'J' ( 74) |1100101 65 [ 7]
|
||||
'K' ( 75) |1100110 66 [ 7]
|
||||
'L' ( 76) |1100111 67 [ 7]
|
||||
'M' ( 77) |1101000 68 [ 7]
|
||||
'N' ( 78) |1101001 69 [ 7]
|
||||
'O' ( 79) |1101010 6a [ 7]
|
||||
'P' ( 80) |1101011 6b [ 7]
|
||||
'Q' ( 81) |1101100 6c [ 7]
|
||||
'R' ( 82) |1101101 6d [ 7]
|
||||
'S' ( 83) |1101110 6e [ 7]
|
||||
'T' ( 84) |1101111 6f [ 7]
|
||||
'U' ( 85) |1110000 70 [ 7]
|
||||
'V' ( 86) |1110001 71 [ 7]
|
||||
'W' ( 87) |1110010 72 [ 7]
|
||||
'X' ( 88) |11111100 fc [ 8]
|
||||
'Y' ( 89) |1110011 73 [ 7]
|
||||
'Z' ( 90) |11111101 fd [ 8]
|
||||
'[' ( 91) |11111111|11011 1ffb [13]
|
||||
'\' ( 92) |11111111|11111110|000 7fff0 [19]
|
||||
']' ( 93) |11111111|11100 1ffc [13]
|
||||
'^' ( 94) |11111111|111100 3ffc [14]
|
||||
'_' ( 95) |100010 22 [ 6]
|
||||
'`' ( 96) |11111111|1111101 7ffd [15]
|
||||
'a' ( 97) |00011 3 [ 5]
|
||||
'b' ( 98) |100011 23 [ 6]
|
||||
'c' ( 99) |00100 4 [ 5]
|
||||
'd' (100) |100100 24 [ 6]
|
||||
'e' (101) |00101 5 [ 5]
|
||||
'f' (102) |100101 25 [ 6]
|
||||
'g' (103) |100110 26 [ 6]
|
||||
'h' (104) |100111 27 [ 6]
|
||||
'i' (105) |00110 6 [ 5]
|
||||
'j' (106) |1110100 74 [ 7]
|
||||
'k' (107) |1110101 75 [ 7]
|
||||
'l' (108) |101000 28 [ 6]
|
||||
'm' (109) |101001 29 [ 6]
|
||||
'n' (110) |101010 2a [ 6]
|
||||
'o' (111) |00111 7 [ 5]
|
||||
'p' (112) |101011 2b [ 6]
|
||||
'q' (113) |1110110 76 [ 7]
|
||||
'r' (114) |101100 2c [ 6]
|
||||
's' (115) |01000 8 [ 5]
|
||||
't' (116) |01001 9 [ 5]
|
||||
'u' (117) |101101 2d [ 6]
|
||||
'v' (118) |1110111 77 [ 7]
|
||||
'w' (119) |1111000 78 [ 7]
|
||||
'x' (120) |1111001 79 [ 7]
|
||||
'y' (121) |1111010 7a [ 7]
|
||||
'z' (122) |1111011 7b [ 7]
|
||||
'{' (123) |11111111|1111110 7ffe [15]
|
||||
'|' (124) |11111111|100 7fc [11]
|
||||
'}' (125) |11111111|111101 3ffd [14]
|
||||
'~' (126) |11111111|11101 1ffd [13]
|
||||
(127) |11111111|11111111|11111111|1100 ffffffc [28]
|
||||
(128) |11111111|11111110|0110 fffe6 [20]
|
||||
(129) |11111111|11111111|010010 3fffd2 [22]
|
||||
(130) |11111111|11111110|0111 fffe7 [20]
|
||||
(131) |11111111|11111110|1000 fffe8 [20]
|
||||
(132) |11111111|11111111|010011 3fffd3 [22]
|
||||
(133) |11111111|11111111|010100 3fffd4 [22]
|
||||
(134) |11111111|11111111|010101 3fffd5 [22]
|
||||
(135) |11111111|11111111|1011001 7fffd9 [23]
|
||||
(136) |11111111|11111111|010110 3fffd6 [22]
|
||||
(137) |11111111|11111111|1011010 7fffda [23]
|
||||
(138) |11111111|11111111|1011011 7fffdb [23]
|
||||
(139) |11111111|11111111|1011100 7fffdc [23]
|
||||
(140) |11111111|11111111|1011101 7fffdd [23]
|
||||
(141) |11111111|11111111|1011110 7fffde [23]
|
||||
(142) |11111111|11111111|11101011 ffffeb [24]
|
||||
(143) |11111111|11111111|1011111 7fffdf [23]
|
||||
(144) |11111111|11111111|11101100 ffffec [24]
|
||||
(145) |11111111|11111111|11101101 ffffed [24]
|
||||
(146) |11111111|11111111|010111 3fffd7 [22]
|
||||
(147) |11111111|11111111|1100000 7fffe0 [23]
|
||||
(148) |11111111|11111111|11101110 ffffee [24]
|
||||
(149) |11111111|11111111|1100001 7fffe1 [23]
|
||||
(150) |11111111|11111111|1100010 7fffe2 [23]
|
||||
(151) |11111111|11111111|1100011 7fffe3 [23]
|
||||
(152) |11111111|11111111|1100100 7fffe4 [23]
|
||||
(153) |11111111|11111110|11100 1fffdc [21]
|
||||
(154) |11111111|11111111|011000 3fffd8 [22]
|
||||
(155) |11111111|11111111|1100101 7fffe5 [23]
|
||||
(156) |11111111|11111111|011001 3fffd9 [22]
|
||||
(157) |11111111|11111111|1100110 7fffe6 [23]
|
||||
(158) |11111111|11111111|1100111 7fffe7 [23]
|
||||
(159) |11111111|11111111|11101111 ffffef [24]
|
||||
(160) |11111111|11111111|011010 3fffda [22]
|
||||
(161) |11111111|11111110|11101 1fffdd [21]
|
||||
(162) |11111111|11111110|1001 fffe9 [20]
|
||||
(163) |11111111|11111111|011011 3fffdb [22]
|
||||
(164) |11111111|11111111|011100 3fffdc [22]
|
||||
(165) |11111111|11111111|1101000 7fffe8 [23]
|
||||
(166) |11111111|11111111|1101001 7fffe9 [23]
|
||||
(167) |11111111|11111110|11110 1fffde [21]
|
||||
(168) |11111111|11111111|1101010 7fffea [23]
|
||||
(169) |11111111|11111111|011101 3fffdd [22]
|
||||
(170) |11111111|11111111|011110 3fffde [22]
|
||||
(171) |11111111|11111111|11110000 fffff0 [24]
|
||||
(172) |11111111|11111110|11111 1fffdf [21]
|
||||
(173) |11111111|11111111|011111 3fffdf [22]
|
||||
(174) |11111111|11111111|1101011 7fffeb [23]
|
||||
(175) |11111111|11111111|1101100 7fffec [23]
|
||||
(176) |11111111|11111111|00000 1fffe0 [21]
|
||||
(177) |11111111|11111111|00001 1fffe1 [21]
|
||||
(178) |11111111|11111111|100000 3fffe0 [22]
|
||||
(179) |11111111|11111111|00010 1fffe2 [21]
|
||||
(180) |11111111|11111111|1101101 7fffed [23]
|
||||
(181) |11111111|11111111|100001 3fffe1 [22]
|
||||
(182) |11111111|11111111|1101110 7fffee [23]
|
||||
(183) |11111111|11111111|1101111 7fffef [23]
|
||||
(184) |11111111|11111110|1010 fffea [20]
|
||||
(185) |11111111|11111111|100010 3fffe2 [22]
|
||||
(186) |11111111|11111111|100011 3fffe3 [22]
|
||||
(187) |11111111|11111111|100100 3fffe4 [22]
|
||||
(188) |11111111|11111111|1110000 7ffff0 [23]
|
||||
(189) |11111111|11111111|100101 3fffe5 [22]
|
||||
(190) |11111111|11111111|100110 3fffe6 [22]
|
||||
(191) |11111111|11111111|1110001 7ffff1 [23]
|
||||
(192) |11111111|11111111|11111000|00 3ffffe0 [26]
|
||||
(193) |11111111|11111111|11111000|01 3ffffe1 [26]
|
||||
(194) |11111111|11111110|1011 fffeb [20]
|
||||
(195) |11111111|11111110|001 7fff1 [19]
|
||||
(196) |11111111|11111111|100111 3fffe7 [22]
|
||||
(197) |11111111|11111111|1110010 7ffff2 [23]
|
||||
(198) |11111111|11111111|101000 3fffe8 [22]
|
||||
(199) |11111111|11111111|11110110|0 1ffffec [25]
|
||||
(200) |11111111|11111111|11111000|10 3ffffe2 [26]
|
||||
(201) |11111111|11111111|11111000|11 3ffffe3 [26]
|
||||
(202) |11111111|11111111|11111001|00 3ffffe4 [26]
|
||||
(203) |11111111|11111111|11111011|110 7ffffde [27]
|
||||
(204) |11111111|11111111|11111011|111 7ffffdf [27]
|
||||
(205) |11111111|11111111|11111001|01 3ffffe5 [26]
|
||||
(206) |11111111|11111111|11110001 fffff1 [24]
|
||||
(207) |11111111|11111111|11110110|1 1ffffed [25]
|
||||
(208) |11111111|11111110|010 7fff2 [19]
|
||||
(209) |11111111|11111111|00011 1fffe3 [21]
|
||||
(210) |11111111|11111111|11111001|10 3ffffe6 [26]
|
||||
(211) |11111111|11111111|11111100|000 7ffffe0 [27]
|
||||
(212) |11111111|11111111|11111100|001 7ffffe1 [27]
|
||||
(213) |11111111|11111111|11111001|11 3ffffe7 [26]
|
||||
(214) |11111111|11111111|11111100|010 7ffffe2 [27]
|
||||
(215) |11111111|11111111|11110010 fffff2 [24]
|
||||
(216) |11111111|11111111|00100 1fffe4 [21]
|
||||
(217) |11111111|11111111|00101 1fffe5 [21]
|
||||
(218) |11111111|11111111|11111010|00 3ffffe8 [26]
|
||||
(219) |11111111|11111111|11111010|01 3ffffe9 [26]
|
||||
(220) |11111111|11111111|11111111|1101 ffffffd [28]
|
||||
(221) |11111111|11111111|11111100|011 7ffffe3 [27]
|
||||
(222) |11111111|11111111|11111100|100 7ffffe4 [27]
|
||||
(223) |11111111|11111111|11111100|101 7ffffe5 [27]
|
||||
(224) |11111111|11111110|1100 fffec [20]
|
||||
(225) |11111111|11111111|11110011 fffff3 [24]
|
||||
(226) |11111111|11111110|1101 fffed [20]
|
||||
(227) |11111111|11111111|00110 1fffe6 [21]
|
||||
(228) |11111111|11111111|101001 3fffe9 [22]
|
||||
(229) |11111111|11111111|00111 1fffe7 [21]
|
||||
(230) |11111111|11111111|01000 1fffe8 [21]
|
||||
(231) |11111111|11111111|1110011 7ffff3 [23]
|
||||
(232) |11111111|11111111|101010 3fffea [22]
|
||||
(233) |11111111|11111111|101011 3fffeb [22]
|
||||
(234) |11111111|11111111|11110111|0 1ffffee [25]
|
||||
(235) |11111111|11111111|11110111|1 1ffffef [25]
|
||||
(236) |11111111|11111111|11110100 fffff4 [24]
|
||||
(237) |11111111|11111111|11110101 fffff5 [24]
|
||||
(238) |11111111|11111111|11111010|10 3ffffea [26]
|
||||
(239) |11111111|11111111|1110100 7ffff4 [23]
|
||||
(240) |11111111|11111111|11111010|11 3ffffeb [26]
|
||||
(241) |11111111|11111111|11111100|110 7ffffe6 [27]
|
||||
(242) |11111111|11111111|11111011|00 3ffffec [26]
|
||||
(243) |11111111|11111111|11111011|01 3ffffed [26]
|
||||
(244) |11111111|11111111|11111100|111 7ffffe7 [27]
|
||||
(245) |11111111|11111111|11111101|000 7ffffe8 [27]
|
||||
(246) |11111111|11111111|11111101|001 7ffffe9 [27]
|
||||
(247) |11111111|11111111|11111101|010 7ffffea [27]
|
||||
(248) |11111111|11111111|11111101|011 7ffffeb [27]
|
||||
(249) |11111111|11111111|11111111|1110 ffffffe [28]
|
||||
(250) |11111111|11111111|11111101|100 7ffffec [27]
|
||||
(251) |11111111|11111111|11111101|101 7ffffed [27]
|
||||
(252) |11111111|11111111|11111101|110 7ffffee [27]
|
||||
(253) |11111111|11111111|11111101|111 7ffffef [27]
|
||||
(254) |11111111|11111111|11111110|000 7fffff0 [27]
|
||||
(255) |11111111|11111111|11111011|10 3ffffee [26]
|
||||
EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]
|
||||
"""
|
||||
|
||||
class Node:
|
||||
|
||||
def __init__(self, term = None):
|
||||
self.term = term
|
||||
self.left = None
|
||||
@@ -20,21 +283,18 @@ class Node:
|
||||
self.id = None
|
||||
self.accept = False
|
||||
|
||||
def to_bin(s):
|
||||
res = []
|
||||
for i in range(0, len(s), 8):
|
||||
x = s[i:i+8]
|
||||
x += '0'*(8 - len(x))
|
||||
a = 0
|
||||
for j in range(8):
|
||||
a *= 2
|
||||
a += ord(x[j]) - ord('0')
|
||||
res.append(a) #chr(a))
|
||||
return res
|
||||
class Context:
|
||||
|
||||
nodes = []
|
||||
def __init__(self):
|
||||
self.next_id_ = 0
|
||||
self.root = Node()
|
||||
|
||||
def insert(node, sym, bits):
|
||||
def next_id(self):
|
||||
id = self.next_id_
|
||||
self.next_id_ += 1
|
||||
return id
|
||||
|
||||
def _add(node, sym, bits):
|
||||
if len(bits) == 0:
|
||||
node.term = sym
|
||||
return
|
||||
@@ -47,67 +307,71 @@ def insert(node, sym, bits):
|
||||
if node.right is None:
|
||||
node.right = Node()
|
||||
child = node.right
|
||||
insert(child, sym, bits[1:])
|
||||
_add(child, sym, bits[1:])
|
||||
|
||||
def traverse(node, bits, syms, start_node, root, depth):
|
||||
if depth == 4:
|
||||
if 256 in syms:
|
||||
syms = []
|
||||
def huffman_tree_add(ctx, sym, bits):
|
||||
_add(ctx.root, sym, bits)
|
||||
|
||||
def _set_node_id(ctx, node, prefix):
|
||||
if node.term is not None:
|
||||
return
|
||||
if len(prefix) <= 7 and [1] * len(prefix) == prefix:
|
||||
node.accept = True
|
||||
node.id = ctx.next_id()
|
||||
_set_node_id(ctx, node.left, prefix + [0])
|
||||
_set_node_id(ctx, node.right, prefix + [1])
|
||||
|
||||
def huffman_tree_set_node_id(ctx):
|
||||
_set_node_id(ctx, ctx.root, [])
|
||||
|
||||
def _traverse(node, sym, start_node, root, left):
|
||||
if left == 0:
|
||||
if sym == 256:
|
||||
sym = None
|
||||
node = None
|
||||
start_node.trans.append((node, bits, syms))
|
||||
start_node.trans.append((node, sym))
|
||||
return
|
||||
|
||||
if node.term is not None:
|
||||
node = root
|
||||
|
||||
def go(node, bit):
|
||||
nbits = list(bits)
|
||||
nbits.append(bit)
|
||||
nsyms = list(syms)
|
||||
def go(node):
|
||||
if node.term is not None:
|
||||
nsyms.append(node.term)
|
||||
traverse(node, nbits, nsyms, start_node, root, depth + 1)
|
||||
assert sym is None
|
||||
nsym = node.term
|
||||
else:
|
||||
nsym = sym
|
||||
|
||||
go(node.left, 0)
|
||||
go(node.right, 1)
|
||||
_traverse(node, nsym, start_node, root, left - 1)
|
||||
|
||||
idseed = 0
|
||||
go(node.left)
|
||||
go(node.right)
|
||||
|
||||
def dfs_setid(node, prefix):
|
||||
if node.term is not None:
|
||||
return
|
||||
if len(prefix) <= 7 and [1] * len(prefix) == prefix:
|
||||
node.accept = True
|
||||
global idseed
|
||||
node.id = idseed
|
||||
idseed += 1
|
||||
dfs_setid(node.left, prefix + [0])
|
||||
dfs_setid(node.right, prefix + [1])
|
||||
|
||||
def dfs(node, root):
|
||||
def _build_transition_table(ctx, node):
|
||||
if node is None:
|
||||
return
|
||||
traverse(node, [], [], node, root, 0)
|
||||
dfs(node.left, root)
|
||||
dfs(node.right, root)
|
||||
_traverse(node, None, node, ctx.root, 4)
|
||||
_build_transition_table(ctx, node.left)
|
||||
_build_transition_table(ctx, node.right)
|
||||
|
||||
def huffman_tree_build_transition_table(ctx):
|
||||
_build_transition_table(ctx, ctx.root)
|
||||
|
||||
NGHTTP2_HUFF_ACCEPTED = 1
|
||||
NGHTTP2_HUFF_SYM = 1 << 1
|
||||
NGHTTP2_HUFF_FAIL = 1 << 2
|
||||
|
||||
def dfs_print(node):
|
||||
def _print_transition_table(node):
|
||||
if node.term is not None:
|
||||
return
|
||||
print '/* {} */'.format(node.id)
|
||||
print '{'
|
||||
for nd, bits, syms in node.trans:
|
||||
outlen = len(syms)
|
||||
for nd, sym in node.trans:
|
||||
flags = 0
|
||||
if outlen == 0:
|
||||
if sym is None:
|
||||
out = 0
|
||||
else:
|
||||
assert(outlen == 1)
|
||||
out = syms[0]
|
||||
out = sym
|
||||
flags |= NGHTTP2_HUFF_SYM
|
||||
if nd is None:
|
||||
id = 0
|
||||
@@ -122,52 +386,50 @@ def dfs_print(node):
|
||||
flags |= NGHTTP2_HUFF_ACCEPTED
|
||||
print ' {{{}, 0x{:02x}, {}}},'.format(id, flags, out)
|
||||
print '},'
|
||||
dfs_print(node.left)
|
||||
dfs_print(node.right)
|
||||
_print_transition_table(node.left)
|
||||
_print_transition_table(node.right)
|
||||
|
||||
symbol_tbl = [(None, 0) for i in range(257)]
|
||||
tables = {}
|
||||
def huffman_tree_print_transition_table(ctx):
|
||||
_print_transition_table(ctx.root)
|
||||
|
||||
root = Node()
|
||||
if __name__ == '__main__':
|
||||
ctx = Context()
|
||||
symbol_tbl = [(None, 0) for i in range(257)]
|
||||
|
||||
for line in sys.stdin:
|
||||
m = re.match(r'.*\(\s*(\d+)\)\s+([|01]+)\s+(\S+)\s+\[\s*(\d+)\].*', line)
|
||||
if m:
|
||||
#print m.group(1), m.group(2), m.group(4)
|
||||
if len(m.group(3)) > 8:
|
||||
raise Error('Code is more than 4 bytes long')
|
||||
sym = int(m.group(1))
|
||||
bits = re.sub(r'\|', '', m.group(2))
|
||||
nbits = int(m.group(4))
|
||||
assert(len(bits) == nbits)
|
||||
binpat = to_bin(bits)
|
||||
assert(len(binpat) == (nbits+7)/8)
|
||||
symbol_tbl[sym] = (binpat, nbits, m.group(3))
|
||||
#print "Inserting", sym
|
||||
insert(root, sym, bits)
|
||||
for line in StringIO.StringIO(HUFFMAN_CODE_TABLE):
|
||||
m = re.match(
|
||||
r'.*\(\s*(\d+)\)\s+([|01]+)\s+(\S+)\s+\[\s*(\d+)\].*', line)
|
||||
if m:
|
||||
sym = int(m.group(1))
|
||||
bits = re.sub(r'\|', '', m.group(2))
|
||||
code = m.group(3)
|
||||
nbits = int(m.group(4))
|
||||
if len(code) > 8:
|
||||
raise Error('Code is more than 4 bytes long')
|
||||
assert(len(bits) == nbits)
|
||||
symbol_tbl[sym] = (nbits, code)
|
||||
huffman_tree_add(ctx, sym, bits)
|
||||
|
||||
dfs_setid(root, [])
|
||||
dfs(root, root)
|
||||
huffman_tree_set_node_id(ctx)
|
||||
huffman_tree_build_transition_table(ctx)
|
||||
|
||||
print '''\
|
||||
print '''\
|
||||
typedef struct {
|
||||
uint32_t nbits;
|
||||
uint32_t code;
|
||||
} nghttp2_huff_sym;
|
||||
'''
|
||||
|
||||
print '''\
|
||||
const nghttp2_huff_sym huff_sym_table[] = {'''
|
||||
for i in range(257):
|
||||
pat = list(symbol_tbl[i][0])
|
||||
pat += [0]*(4 - len(pat))
|
||||
print '''\
|
||||
const nghttp2_huff_sym huff_sym_table[] = {'''
|
||||
for i in range(257):
|
||||
print '''\
|
||||
{{ {}, 0x{}u }}{}\
|
||||
'''.format(symbol_tbl[i][1], symbol_tbl[i][2], ',' if i < 256 else '')
|
||||
print '};'
|
||||
print ''
|
||||
'''.format(symbol_tbl[i][0], symbol_tbl[i][1], ',' if i < 256 else '')
|
||||
print '};'
|
||||
print ''
|
||||
|
||||
print '''\
|
||||
print '''\
|
||||
enum {{
|
||||
NGHTTP2_HUFF_ACCEPTED = {},
|
||||
NGHTTP2_HUFF_SYM = {},
|
||||
@@ -175,7 +437,7 @@ enum {{
|
||||
}} nghttp2_huff_decode_flag;
|
||||
'''.format(NGHTTP2_HUFF_ACCEPTED, NGHTTP2_HUFF_SYM, NGHTTP2_HUFF_FAIL)
|
||||
|
||||
print '''\
|
||||
print '''\
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t flags;
|
||||
@@ -183,7 +445,7 @@ typedef struct {
|
||||
} nghttp2_huff_decode;
|
||||
'''
|
||||
|
||||
print '''\
|
||||
print '''\
|
||||
const nghttp2_huff_decode huff_decode_table[][16] = {'''
|
||||
dfs_print(root)
|
||||
print '};'
|
||||
huffman_tree_print_transition_table(ctx)
|
||||
print '};'
|
||||
|
||||
@@ -10,39 +10,17 @@
|
||||
from __future__ import unicode_literals
|
||||
import re, sys
|
||||
|
||||
def hash(s):
|
||||
h = 0
|
||||
for c in s:
|
||||
h = h * 31 + ord(c)
|
||||
return h & ((1 << 32) - 1)
|
||||
|
||||
entries = []
|
||||
for line in sys.stdin:
|
||||
m = re.match(r'(\d+)\s+(\S+)\s+(\S.*)?', line)
|
||||
val = m.group(3).strip() if m.group(3) else ''
|
||||
entries.append((hash(m.group(2)), int(m.group(1)), m.group(2), val))
|
||||
|
||||
entries.sort()
|
||||
|
||||
print '/* Sorted by hash(name) and its table index */'
|
||||
print 'static nghttp2_hd_static_entry static_table[] = {'
|
||||
for ent in entries:
|
||||
print 'MAKE_STATIC_ENT({}, "{}", "{}", {}u, {}u),'\
|
||||
.format(ent[1] - 1, ent[2], ent[3], ent[0], hash(ent[3]))
|
||||
print '};'
|
||||
|
||||
print ''
|
||||
|
||||
print '/* Index to the position in static_table */'
|
||||
print 'const size_t static_table_index[] = {'
|
||||
for i in range(len(entries)):
|
||||
for j, ent in enumerate(entries):
|
||||
if ent[1] - 1 == i:
|
||||
sys.stdout.write('{: <2d},'.format(j))
|
||||
break
|
||||
if (i + 1) % 16 == 0:
|
||||
sys.stdout.write('\n')
|
||||
else:
|
||||
sys.stdout.write(' ')
|
||||
entries.append((int(m.group(1)), m.group(2), val))
|
||||
|
||||
print 'static nghttp2_hd_entry static_table[] = {'
|
||||
idx = 0
|
||||
for i, ent in enumerate(entries):
|
||||
if entries[idx][1] != ent[1]:
|
||||
idx = i
|
||||
print 'MAKE_STATIC_ENT("{}", "{}", {}),'\
|
||||
.format(ent[1], ent[2], entries[idx][0] - 1)
|
||||
print '};'
|
||||
|
||||
4
python/.gitignore
vendored
Normal file
4
python/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# generated files
|
||||
MANIFEST
|
||||
dist/
|
||||
setup.py
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user