libnghttp2: Remove dependency to zlib

We inherited gzip compression API from spdylay codebase.  In spdylay,
the cost of having such API is almost free because spdylay requires
zlib for header compression.  nghttp2 no longer uses gzip to header
compression.  zlib dependency exists just for gzip compression API,
which is not an essential.  So we decided to move gzip code to under
src and remove zlib dependency from libnghttp2 itself.  As nghttp2
package, we depend on zlib to compile tools under src.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-05-06 23:10:50 +09:00
parent 704f362804
commit 4f027c1562
14 changed files with 154 additions and 198 deletions

View File

@ -193,11 +193,13 @@ esac
# zlib # zlib
if test "x$android_build" = "xyes"; then if test "x$android_build" = "xyes"; then
# Use zlib provided by NDK # Use zlib provided by NDK
LIBS="-lz $LIBS" SRC_LIBS="-lz $SRC_LIBS"
else else
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3]) PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
LIBS="$ZLIB_LIBS $LIBS"
CFLAGS="$CFLAGS $ZLIB_CFLAGS" if test "x${have_zlib}" = "xno"; then
AC_MSG_NOTICE($ZLIB_PKG_ERRORS)
fi
fi fi
# cunit # cunit
@ -304,10 +306,11 @@ fi
AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ]) AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ])
# The nghttp, nghttpd and nghttpx under src depend on OpenSSL and # The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL
# libevent_openssl # and libevent_openssl
enable_app=no enable_app=no
if test "x${request_app}" != "xno" && if test "x${request_app}" != "xno" &&
test "x${have_zlib}" = "xyes" &&
test "x${have_openssl}" = "xyes" && test "x${have_openssl}" = "xyes" &&
test "x${have_libevent_openssl}" = "xyes"; then test "x${have_libevent_openssl}" = "xyes"; then
enable_app=yes enable_app=yes

View File

@ -72,8 +72,6 @@ struct Connection {
}; };
struct Request { struct Request {
/* The gzip stream inflater for the compressed response. */
nghttp2_gzip *inflater;
char *host; char *host;
/* In this program, path contains query component as well. */ /* In this program, path contains query component as well. */
char *path; char *path;
@ -139,36 +137,6 @@ static void diec(const char *func, int error_code)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
static char CONTENT_LENGTH[] = "content-encoding";
static size_t CONTENT_LENGTH_LEN = sizeof(CONTENT_LENGTH) - 1;
static char GZIP[] = "gzip";
static size_t GZIP_LEN = sizeof(GZIP) - 1;
/*
* Check response is content-encoding: gzip. We need this because
* HTTP/2 client is required to support gzip.
*/
static void check_gzip(struct Request *req, nghttp2_nv *nva, size_t nvlen)
{
size_t i;
if(req->inflater) {
return;
}
for(i = 0; i < nvlen; ++i) {
if(CONTENT_LENGTH_LEN == nva[i].namelen &&
memcmp(CONTENT_LENGTH, nva[i].name, nva[i].namelen) == 0 &&
GZIP_LEN == nva[i].valuelen &&
memcmp(GZIP, nva[i].value, nva[i].valuelen) == 0) {
int rv;
rv = nghttp2_gzip_inflate_new(&req->inflater);
if(rv != 0) {
die("Can't allocate inflate stream.");
}
break;
}
}
}
/* /*
* The implementation of nghttp2_send_callback type. Here we write * The implementation of nghttp2_send_callback type. Here we write
* |data| with size |length| to the network and return the number of * |data| with size |length| to the network and return the number of
@ -290,7 +258,6 @@ static int on_frame_recv_callback(nghttp2_session *session,
struct Request *req; struct Request *req;
req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id); req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(req) { if(req) {
check_gzip(req, frame->headers.nva, frame->headers.nvlen);
printf("[INFO] C <---------------------------- S (HEADERS)\n"); printf("[INFO] C <---------------------------- S (HEADERS)\n");
for(i = 0; i < frame->headers.nvlen; ++i) { for(i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout); fwrite(nva[i].name, nva[i].namelen, 1, stdout);
@ -351,25 +318,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
if(req) { if(req) {
printf("[INFO] C <---------------------------- S (DATA chunk)\n" printf("[INFO] C <---------------------------- S (DATA chunk)\n"
"%lu bytes\n", (unsigned long int)len); "%lu bytes\n", (unsigned long int)len);
if(req->inflater) {
while(len > 0) {
uint8_t out[MAX_OUTLEN];
size_t outlen = MAX_OUTLEN;
size_t tlen = len;
int rv;
rv = nghttp2_gzip_inflate(req->inflater, out, &outlen, data, &tlen);
if(rv == -1) {
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
NGHTTP2_INTERNAL_ERROR);
break;
}
fwrite(out, 1, outlen, stdout);
data += tlen;
len -= tlen;
}
} else {
fwrite(data, 1, len, stdout); fwrite(data, 1, len, stdout);
}
printf("\n"); printf("\n");
} }
return 0; return 0;
@ -561,7 +510,6 @@ static void request_init(struct Request *req, const struct URI *uri)
req->path = strcopy(uri->path, uri->pathlen); req->path = strcopy(uri->path, uri->pathlen);
req->hostport = strcopy(uri->hostport, uri->hostportlen); req->hostport = strcopy(uri->hostport, uri->hostportlen);
req->stream_id = -1; req->stream_id = -1;
req->inflater = NULL;
} }
static void request_free(struct Request *req) static void request_free(struct Request *req)
@ -569,7 +517,6 @@ static void request_free(struct Request *req)
free(req->host); free(req->host);
free(req->path); free(req->path);
free(req->hostport); free(req->hostport);
nghttp2_gzip_inflate_del(req->inflater);
} }
/* /*

View File

@ -37,7 +37,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_stream.c nghttp2_outbound_item.c \ nghttp2_stream.c nghttp2_outbound_item.c \
nghttp2_session.c nghttp2_submit.c \ nghttp2_session.c nghttp2_submit.c \
nghttp2_helper.c \ nghttp2_helper.c \
nghttp2_npn.c nghttp2_gzip.c \ nghttp2_npn.c \
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \ nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \
nghttp2_version.c \ nghttp2_version.c \
nghttp2_priority_spec.c \ nghttp2_priority_spec.c \
@ -47,7 +47,7 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_frame.h \ nghttp2_frame.h \
nghttp2_buf.h \ nghttp2_buf.h \
nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \ nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \
nghttp2_npn.h nghttp2_gzip.h \ nghttp2_npn.h \
nghttp2_submit.h nghttp2_outbound_item.h \ nghttp2_submit.h nghttp2_outbound_item.h \
nghttp2_net.h \ nghttp2_net.h \
nghttp2_hd.h nghttp2_hd_huffman.h \ nghttp2_hd.h nghttp2_hd_huffman.h \

View File

@ -2726,96 +2726,6 @@ int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs);
int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen, int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen); const unsigned char *in, unsigned int inlen);
struct nghttp2_gzip;
/**
* @struct
*
* The gzip stream to inflate data. The details of this structure are
* intentionally hidden from the public API.
*/
typedef struct nghttp2_gzip nghttp2_gzip;
/**
* @function
*
* A helper function to set up a per request gzip stream to inflate
* data.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_GZIP`
* The initialization of gzip stream failed.
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
*/
int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr);
/**
* @function
*
* Frees the inflate stream. The |inflater| may be ``NULL``.
*/
void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater);
/**
* @function
*
* Inflates data in |in| with the length |*inlen_ptr| and stores the
* inflated data to |out| which has allocated size at least
* |*outlen_ptr|. On return, |*outlen_ptr| is updated to represent
* the number of data written in |out|. Similarly, |*inlen_ptr| is
* updated to represent the number of input bytes processed.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_GZIP`
* The inflation of gzip stream failed.
*
* The example follows::
*
* void on_data_chunk_recv_callback(nghttp2_session *session,
* uint8_t flags,
* int32_t stream_id,
* const uint8_t *data, size_t len,
* void *user_data)
* {
* ...
* req = nghttp2_session_get_stream_user_data(session, stream_id);
* nghttp2_gzip *inflater = req->inflater;
* while(len > 0) {
* uint8_t out[MAX_OUTLEN];
* size_t outlen = MAX_OUTLEN;
* size_t tlen = len;
* int rv;
* rv = nghttp2_gzip_inflate(inflater, out, &outlen, data, &tlen);
* if(rv != 0) {
* nghttp2_submit_rst_stream(session, stream_id,
* NGHTTP2_INTERNAL_ERROR);
* break;
* }
* ... Do stuff ...
* data += tlen;
* len -= tlen;
* }
* ....
* }
*/
int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
uint8_t *out, size_t *outlen_ptr,
const uint8_t *in, size_t *inlen_ptr);
/**
* @function
*
* Returns nonzero if |inflater| sees the end of deflate stream.
* After this function returns nonzero, `nghttp2_gzip_inflate()` with
* |inflater| gets to return error.
*/
int nghttp2_gzip_inflate_finished(nghttp2_gzip *inflater);
/** /**
* @function * @function
* *

View File

@ -30,5 +30,4 @@ Description: HTTP/2 C library
URL: https://github.com/tatsuhiro-t/nghttp2 URL: https://github.com/tatsuhiro-t/nghttp2
Version: @VERSION@ Version: @VERSION@
Libs: -L${libdir} -lnghttp2 Libs: -L${libdir} -lnghttp2
Libs.private: -lz
Cflags: -I${includedir} Cflags: -I${includedir}

View File

@ -1,39 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* 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.
*/
#ifndef NGHTTP2_GZIP_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <zlib.h>
#include <nghttp2/nghttp2.h>
struct nghttp2_gzip {
z_stream zst;
int8_t finished;
};
#endif /* NGHTTP2_GZIP_H */

View File

@ -36,6 +36,7 @@ AM_CPPFLAGS = \
@LIBEVENT_OPENSSL_CFLAGS@ \ @LIBEVENT_OPENSSL_CFLAGS@ \
@OPENSSL_CFLAGS@ \ @OPENSSL_CFLAGS@ \
@JANSSON_CFLAGS@ \ @JANSSON_CFLAGS@ \
@ZLIB_CFLAGS@ \
@DEFS@ @DEFS@
AM_LDFLAGS = \ AM_LDFLAGS = \
@LIBSPDYLAY_LIBS@ \ @LIBSPDYLAY_LIBS@ \
@ -43,6 +44,7 @@ AM_LDFLAGS = \
@LIBEVENT_OPENSSL_LIBS@ \ @LIBEVENT_OPENSSL_LIBS@ \
@OPENSSL_LIBS@ \ @OPENSSL_LIBS@ \
@JANSSON_LIBS@ \ @JANSSON_LIBS@ \
@ZLIB_LIBS@ \
@JEMALLOC_LIBS@ \ @JEMALLOC_LIBS@ \
@SRC_LIBS@ @SRC_LIBS@
@ -54,8 +56,9 @@ if ENABLE_APP
bin_PROGRAMS += nghttp nghttpd nghttpx h2load bin_PROGRAMS += nghttp nghttpd nghttpx h2load
HELPER_OBJECTS = util.cc http2.cc timegm.c app_helper.cc HELPER_OBJECTS = util.cc http2.cc timegm.c app_helper.cc nghttp2_gzip.c
HELPER_HFILES = util.h http2.h timegm.h app_helper.h nghttp2_config.h HELPER_HFILES = util.h http2.h timegm.h app_helper.h nghttp2_config.h \
nghttp2_gzip.h
HTML_PARSER_OBJECTS = HTML_PARSER_OBJECTS =
HTML_PARSER_HFILES = HtmlParser.h HTML_PARSER_HFILES = HtmlParser.h
@ -124,7 +127,8 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
shrpx_downstream_test.cc shrpx_downstream_test.h \ shrpx_downstream_test.cc shrpx_downstream_test.h \
shrpx_config_test.cc shrpx_config_test.h \ shrpx_config_test.cc shrpx_config_test.h \
http2_test.cc http2_test.h \ http2_test.cc http2_test.h \
util_test.cc util_test.h util_test.cc util_test.h \
nghttp2_gzip_test.c nghttp2_gzip_test.h
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS}\ nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS}\
-DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\" -DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\"
nghttpx_unittest_LDFLAGS = -static nghttpx_unittest_LDFLAGS = -static

View File

@ -68,6 +68,7 @@
#include "util.h" #include "util.h"
#include "base64.h" #include "base64.h"
#include "http2.h" #include "http2.h"
#include "nghttp2_gzip.h"
#ifndef O_BINARY #ifndef O_BINARY
# define O_BINARY (0) # define O_BINARY (0)

132
src/nghttp2_gzip.h Normal file
View File

@ -0,0 +1,132 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* 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.
*/
#ifndef NGHTTP2_GZIP_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <zlib.h>
#include <nghttp2/nghttp2.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @struct
*
* The gzip stream to inflate data.
*/
typedef struct {
z_stream zst;
int8_t finished;
} nghttp2_gzip;
/**
* @function
*
* A helper function to set up a per request gzip stream to inflate
* data.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_GZIP`
* The initialization of gzip stream failed.
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
*/
int nghttp2_gzip_inflate_new(nghttp2_gzip **inflater_ptr);
/**
* @function
*
* Frees the inflate stream. The |inflater| may be ``NULL``.
*/
void nghttp2_gzip_inflate_del(nghttp2_gzip *inflater);
/**
* @function
*
* Inflates data in |in| with the length |*inlen_ptr| and stores the
* inflated data to |out| which has allocated size at least
* |*outlen_ptr|. On return, |*outlen_ptr| is updated to represent
* the number of data written in |out|. Similarly, |*inlen_ptr| is
* updated to represent the number of input bytes processed.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_GZIP`
* The inflation of gzip stream failed.
*
* The example follows::
*
* void on_data_chunk_recv_callback(nghttp2_session *session,
* uint8_t flags,
* int32_t stream_id,
* const uint8_t *data, size_t len,
* void *user_data)
* {
* ...
* req = nghttp2_session_get_stream_user_data(session, stream_id);
* nghttp2_gzip *inflater = req->inflater;
* while(len > 0) {
* uint8_t out[MAX_OUTLEN];
* size_t outlen = MAX_OUTLEN;
* size_t tlen = len;
* int rv;
* rv = nghttp2_gzip_inflate(inflater, out, &outlen, data, &tlen);
* if(rv != 0) {
* nghttp2_submit_rst_stream(session, stream_id,
* NGHTTP2_INTERNAL_ERROR);
* break;
* }
* ... Do stuff ...
* data += tlen;
* len -= tlen;
* }
* ....
* }
*/
int nghttp2_gzip_inflate(nghttp2_gzip *inflater,
uint8_t *out, size_t *outlen_ptr,
const uint8_t *in, size_t *inlen_ptr);
/**
* @function
*
* Returns nonzero if |inflater| sees the end of deflate stream.
* After this function returns nonzero, `nghttp2_gzip_inflate()` with
* |inflater| gets to return error.
*/
int nghttp2_gzip_inflate_finished(nghttp2_gzip *inflater);
#ifdef __cplusplus
}
#endif
#endif /* NGHTTP2_GZIP_H */

View File

@ -116,7 +116,8 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "util_to_base64", !CU_add_test(pSuite, "util_to_base64",
shrpx::test_util_to_base64) || shrpx::test_util_to_base64) ||
!CU_add_test(pSuite, "util_percent_encode_token", !CU_add_test(pSuite, "util_percent_encode_token",
shrpx::test_util_percent_encode_token)) { shrpx::test_util_percent_encode_token) ||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)) {
CU_cleanup_registry(); CU_cleanup_registry();
return CU_get_error(); return CU_get_error();
} }

View File

@ -34,7 +34,6 @@
#include "nghttp2_stream_test.h" #include "nghttp2_stream_test.h"
#include "nghttp2_hd_test.h" #include "nghttp2_hd_test.h"
#include "nghttp2_npn_test.h" #include "nghttp2_npn_test.h"
#include "nghttp2_gzip_test.h"
#include "nghttp2_helper_test.h" #include "nghttp2_helper_test.h"
#include "nghttp2_buf_test.h" #include "nghttp2_buf_test.h"
@ -279,7 +278,6 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "hd_deflate_inflate", !CU_add_test(pSuite, "hd_deflate_inflate",
test_nghttp2_hd_deflate_inflate) || test_nghttp2_hd_deflate_inflate) ||
!CU_add_test(pSuite, "hd_no_index", test_nghttp2_hd_no_index) || !CU_add_test(pSuite, "hd_no_index", test_nghttp2_hd_no_index) ||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
!CU_add_test(pSuite, "adjust_local_window_size", !CU_add_test(pSuite, "adjust_local_window_size",
test_nghttp2_adjust_local_window_size) || test_nghttp2_adjust_local_window_size) ||
!CU_add_test(pSuite, "check_header_name", !CU_add_test(pSuite, "check_header_name",