Commit 4f027c15 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

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.
parent 704f3628
......@@ -193,11 +193,13 @@ esac
# zlib
if test "x$android_build" = "xyes"; then
# Use zlib provided by NDK
LIBS="-lz $LIBS"
SRC_LIBS="-lz $SRC_LIBS"
else
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3])
LIBS="$ZLIB_LIBS $LIBS"
CFLAGS="$CFLAGS $ZLIB_CFLAGS"
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
if test "x${have_zlib}" = "xno"; then
AC_MSG_NOTICE($ZLIB_PKG_ERRORS)
fi
fi
# cunit
......@@ -304,10 +306,11 @@ fi
AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ])
# The nghttp, nghttpd and nghttpx under src depend on OpenSSL and
# libevent_openssl
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL
# and libevent_openssl
enable_app=no
if test "x${request_app}" != "xno" &&
test "x${have_zlib}" = "xyes" &&
test "x${have_openssl}" = "xyes" &&
test "x${have_libevent_openssl}" = "xyes"; then
enable_app=yes
......
......@@ -72,8 +72,6 @@ struct Connection {
};
struct Request {
/* The gzip stream inflater for the compressed response. */
nghttp2_gzip *inflater;
char *host;
/* In this program, path contains query component as well. */
char *path;
......@@ -139,36 +137,6 @@ static void diec(const char *func, int error_code)
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
* |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;
req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(req) {
check_gzip(req, frame->headers.nva, frame->headers.nvlen);
printf("[INFO] C <---------------------------- S (HEADERS)\n");
for(i = 0; i < frame->headers.nvlen; ++i) {
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) {
printf("[INFO] C <---------------------------- S (DATA chunk)\n"
"%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");
}
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->hostport = strcopy(uri->hostport, uri->hostportlen);
req->stream_id = -1;
req->inflater = NULL;
}
static void request_free(struct Request *req)
......@@ -569,7 +517,6 @@ static void request_free(struct Request *req)
free(req->host);
free(req->path);
free(req->hostport);
nghttp2_gzip_inflate_del(req->inflater);
}
/*
......
......@@ -37,7 +37,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_stream.c nghttp2_outbound_item.c \
nghttp2_session.c nghttp2_submit.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_version.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_buf.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_net.h \
nghttp2_hd.h nghttp2_hd_huffman.h \
......
......@@ -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,
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
*
......
......@@ -30,5 +30,4 @@ Description: HTTP/2 C library
URL: https://github.com/tatsuhiro-t/nghttp2
Version: @VERSION@
Libs: -L${libdir} -lnghttp2
Libs.private: -lz
Cflags: -I${includedir}
......@@ -36,6 +36,7 @@ AM_CPPFLAGS = \
@LIBEVENT_OPENSSL_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@JANSSON_CFLAGS@ \
@ZLIB_CFLAGS@ \
@DEFS@
AM_LDFLAGS = \
@LIBSPDYLAY_LIBS@ \
......@@ -43,6 +44,7 @@ AM_LDFLAGS = \
@LIBEVENT_OPENSSL_LIBS@ \
@OPENSSL_LIBS@ \
@JANSSON_LIBS@ \
@ZLIB_LIBS@ \
@JEMALLOC_LIBS@ \
@SRC_LIBS@
......@@ -54,8 +56,9 @@ if ENABLE_APP
bin_PROGRAMS += nghttp nghttpd nghttpx h2load
HELPER_OBJECTS = util.cc http2.cc timegm.c app_helper.cc
HELPER_HFILES = util.h http2.h timegm.h app_helper.h nghttp2_config.h
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 \
nghttp2_gzip.h
HTML_PARSER_OBJECTS =
HTML_PARSER_HFILES = HtmlParser.h
......@@ -124,7 +127,8 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
shrpx_downstream_test.cc shrpx_downstream_test.h \
shrpx_config_test.cc shrpx_config_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}\
-DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\"
nghttpx_unittest_LDFLAGS = -static
......
......@@ -68,6 +68,7 @@
#include "util.h"
#include "base64.h"
#include "http2.h"
#include "nghttp2_gzip.h"
#ifndef O_BINARY
# define O_BINARY (0)
......
......@@ -31,9 +31,102 @@
#include <nghttp2/nghttp2.h>
struct nghttp2_gzip {
#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 */
......@@ -116,7 +116,8 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "util_to_base64",
shrpx::test_util_to_base64) ||
!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();
return CU_get_error();
}
......
......@@ -34,7 +34,6 @@
#include "nghttp2_stream_test.h"
#include "nghttp2_hd_test.h"
#include "nghttp2_npn_test.h"
#include "nghttp2_gzip_test.h"
#include "nghttp2_helper_test.h"
#include "nghttp2_buf_test.h"
......@@ -279,7 +278,6 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "hd_deflate_inflate",
test_nghttp2_hd_deflate_inflate) ||
!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",
test_nghttp2_adjust_local_window_size) ||
!CU_add_test(pSuite, "check_header_name",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment